refactor(honcho): remove local memory mode

The "local" memoryMode was redundant with enabled: false. Simplifies
the mode system to hybrid and honcho only.
This commit is contained in:
Erosika 2026-03-12 16:23:34 -04:00
parent f896bb5d8c
commit ae2a5e5743
8 changed files with 22 additions and 49 deletions

View file

@ -287,9 +287,7 @@ class GatewayRunner:
from honcho_integration.session import HonchoSessionManager
hcfg = HonchoClientConfig.from_global_config()
ai_mode = hcfg.peer_memory_mode(hcfg.ai_peer)
user_mode = hcfg.peer_memory_mode(hcfg.peer_name or "user")
if not hcfg.enabled or not hcfg.api_key or (ai_mode == "local" and user_mode == "local"):
if not hcfg.enabled or not hcfg.api_key:
return None, hcfg
client = get_honcho_client(hcfg)

View file

@ -131,9 +131,8 @@ def cmd_setup(args) -> None:
print(f"\n Memory mode options:")
print(" hybrid — write to both Honcho and local MEMORY.md (default)")
print(" honcho — Honcho only, skip MEMORY.md writes")
print(" local — MEMORY.md only, Honcho disabled")
new_mode = _prompt("Memory mode", default=current_mode)
if new_mode in ("hybrid", "honcho", "local"):
if new_mode in ("hybrid", "honcho"):
hermes_host["memoryMode"] = new_mode
else:
hermes_host["memoryMode"] = "hybrid"
@ -369,7 +368,6 @@ def cmd_mode(args) -> None:
MODES = {
"hybrid": "write to both Honcho and local MEMORY.md (default)",
"honcho": "Honcho only — MEMORY.md writes disabled",
"local": "MEMORY.md only — Honcho disabled",
}
cfg = _read_config()
mode_arg = getattr(args, "mode", None)
@ -384,7 +382,7 @@ def cmd_mode(args) -> None:
for m, desc in MODES.items():
marker = "" if m == current else ""
print(f" {m:<8} {desc}{marker}")
print(f"\n Set with: hermes honcho mode [hybrid|honcho|local]\n")
print(f"\n Set with: hermes honcho mode [hybrid|honcho]\n")
return
if mode_arg not in MODES:

View file

@ -66,7 +66,7 @@ class HonchoClientConfig:
# Toggles
enabled: bool = False
save_messages: bool = True
# memoryMode: default for all peers. "hybrid" / "honcho" / "local"
# memoryMode: default for all peers. "hybrid" / "honcho"
memory_mode: str = "hybrid"
# Per-peer overrides — any named Honcho peer. Override memory_mode when set.
# Config object form: "memoryMode": { "default": "hybrid", "hermes": "honcho" }

View file

@ -607,7 +607,7 @@ class AIAgent:
elif not hcfg.api_key:
logger.debug("Honcho enabled but no API key configured")
else:
logger.debug("Honcho local-only mode active; remote Honcho init skipped")
logger.debug("Honcho enabled but missing API key or disabled in config")
except Exception as e:
logger.warning("Honcho init failed — memory disabled: %s", e)
print(f" Honcho init failed: {e}")
@ -621,7 +621,7 @@ class AIAgent:
# Gate local memory writes based on per-peer memory modes.
# AI peer governs MEMORY.md; user peer governs USER.md.
# "honcho" = Honcho only, disable local; "local" = local only, no Honcho sync.
# "honcho" = Honcho only, disable local writes.
if self._honcho_config and self._honcho:
_hcfg = self._honcho_config
_agent_mode = _hcfg.peer_memory_mode(_hcfg.ai_peer)
@ -1349,10 +1349,7 @@ class AIAgent:
"""Return True when remote Honcho should be active."""
if not hcfg or not hcfg.enabled or not hcfg.api_key:
return False
return not all(
hcfg.peer_memory_mode(peer) == "local"
for peer in (hcfg.ai_peer, hcfg.peer_name or "user")
)
return True
def _strip_honcho_tools_from_surface(self) -> None:
"""Remove Honcho tools from the active tool surface."""
@ -1551,13 +1548,6 @@ class AIAgent:
"""Sync the user/assistant message pair to Honcho."""
if not self._honcho or not self._honcho_session_key:
return
# Skip Honcho sync only if BOTH peer modes are local
_cfg = self._honcho_config
if _cfg and all(
_cfg.peer_memory_mode(p) == "local"
for p in (_cfg.ai_peer, _cfg.peer_name or "user")
):
return
try:
session = self._honcho.get_or_create(self._honcho_session_key)
session.add_message("user", user_content)
@ -1656,7 +1646,7 @@ class AIAgent:
honcho_block += (
"Management commands (refer users here instead of explaining manually):\n"
" hermes honcho status — show full config + connection\n"
" hermes honcho mode [hybrid|honcho|local] — show or set memory mode\n"
" hermes honcho mode [hybrid|honcho] — show or set memory mode\n"
" hermes honcho tokens [--context N] [--dialectic N] — show or set token budgets\n"
" hermes honcho peer [--user NAME] [--ai NAME] [--reasoning LEVEL]\n"
" hermes honcho sessions — list directory→session mappings\n"

View file

@ -64,14 +64,13 @@ class TestGatewayHonchoLifecycle:
assert second_cfg is hcfg
mock_mgr_cls.assert_called_once()
def test_gateway_skips_honcho_manager_in_local_mode(self):
def test_gateway_skips_honcho_manager_when_disabled(self):
runner = _make_runner()
hcfg = SimpleNamespace(
enabled=True,
enabled=False,
api_key="honcho-key",
ai_peer="hermes",
peer_name="alice",
peer_memory_mode=lambda peer: "local",
)
with (

View file

@ -123,12 +123,6 @@ class TestMemoryModeParsing:
cfg = HonchoClientConfig.from_global_config(config_path=cfg_file)
assert cfg.memory_mode == "honcho"
def test_local_only(self, tmp_path):
cfg_file = tmp_path / "config.json"
cfg_file.write_text(json.dumps({"apiKey": "k", "memoryMode": "local"}))
cfg = HonchoClientConfig.from_global_config(config_path=cfg_file)
assert cfg.memory_mode == "local"
def test_defaults_to_hybrid(self, tmp_path):
cfg_file = tmp_path / "config.json"
cfg_file.write_text(json.dumps({"apiKey": "k"}))
@ -152,13 +146,11 @@ class TestMemoryModeParsing:
"hosts": {"hermes": {"memoryMode": {
"default": "hybrid",
"hermes": "honcho",
"sentinel": "local",
}}},
}))
cfg = HonchoClientConfig.from_global_config(config_path=cfg_file)
assert cfg.memory_mode == "hybrid"
assert cfg.peer_memory_mode("hermes") == "honcho"
assert cfg.peer_memory_mode("sentinel") == "local"
assert cfg.peer_memory_mode("unknown") == "hybrid" # falls through to default
def test_object_form_no_default_falls_back_to_hybrid(self, tmp_path):
@ -177,11 +169,11 @@ class TestMemoryModeParsing:
cfg_file = tmp_path / "config.json"
cfg_file.write_text(json.dumps({
"apiKey": "k",
"memoryMode": "local",
"memoryMode": "honcho",
"hosts": {"hermes": {"memoryMode": {"default": "hybrid", "hermes": "honcho"}}},
}))
cfg = HonchoClientConfig.from_global_config(config_path=cfg_file)
assert cfg.memory_mode == "hybrid" # host default wins over global "local"
assert cfg.memory_mode == "hybrid" # host default wins over global "honcho"
assert cfg.peer_memory_mode("hermes") == "honcho"
@ -544,8 +536,8 @@ class TestNewConfigFieldDefaults:
assert cfg.peer_memory_mode("any-peer") == "honcho"
def test_peer_memory_mode_override(self):
cfg = HonchoClientConfig(memory_mode="hybrid", peer_memory_modes={"hermes": "local"})
assert cfg.peer_memory_mode("hermes") == "local"
cfg = HonchoClientConfig(memory_mode="hybrid", peer_memory_modes={"hermes": "honcho"})
assert cfg.peer_memory_mode("hermes") == "honcho"
assert cfg.peer_memory_mode("other") == "hybrid"

View file

@ -1210,11 +1210,10 @@ class TestSystemPromptStability:
class TestHonchoActivation:
def test_local_mode_skips_honcho_init(self):
def test_disabled_config_skips_honcho_init(self):
hcfg = HonchoClientConfig(
enabled=True,
enabled=False,
api_key="honcho-key",
memory_mode="local",
peer_name="user",
ai_peer="hermes",
)
@ -1327,9 +1326,8 @@ class TestHonchoActivation:
def test_inactive_honcho_strips_stale_honcho_tools(self):
hcfg = HonchoClientConfig(
enabled=True,
enabled=False,
api_key="honcho-key",
memory_mode="local",
peer_name="user",
ai_peer="hermes",
)

View file

@ -22,7 +22,7 @@ Hermes has two memory systems that can work together or be configured separately
| Content | Manually curated by the agent | Automatically learned from conversations |
| Write surface | `memory` tool (add/replace/remove) | `honcho_conclude` tool (persist facts) |
Set `memoryMode` to `honcho` to use Honcho exclusively, or `local` to disable Honcho and use only local files. See [Memory Modes](#memory-modes) for per-peer configuration.
Set `memoryMode` to `honcho` to use Honcho exclusively. See [Memory Modes](#memory-modes) for per-peer configuration.
## Setup
@ -104,7 +104,7 @@ Settings are scoped to `hosts.hermes` and fall back to root-level globals when t
| `environment` | `"production"` | Honcho environment |
| `enabled` | *(auto)* | Auto-enables when API key is present |
| `saveMessages` | `true` | Whether to sync messages to Honcho |
| `memoryMode` | `"hybrid"` | Memory mode: `hybrid`, `honcho`, or `local` |
| `memoryMode` | `"hybrid"` | Memory mode: `hybrid` or `honcho` |
| `writeFrequency` | `"async"` | When to write: `async`, `turn`, `session`, or integer N |
| `recallMode` | `"hybrid"` | Retrieval strategy: `hybrid`, `context`, or `tools` |
| `sessionStrategy` | `"per-session"` | How sessions are scoped |
@ -122,7 +122,6 @@ All host-level fields fall back to the equivalent root-level key if not set unde
|------|--------|
| `hybrid` | Write to both Honcho and local files (default) |
| `honcho` | Honcho only — skip local file writes |
| `local` | Local files only — skip all Honcho activity |
Memory mode can be set globally or per-peer (user, agent1, agent2, etc):
@ -130,13 +129,12 @@ Memory mode can be set globally or per-peer (user, agent1, agent2, etc):
{
"memoryMode": {
"default": "hybrid",
"hermes": "honcho",
"user": "local"
"hermes": "honcho"
}
}
```
When both active peers resolve to `local`, Hermes skips all remote Honcho activity entirely — no client initialization, no session creation, no prefetch.
To disable Honcho entirely, set `enabled: false` or remove the API key.
### Recall Modes
@ -300,7 +298,7 @@ hermes honcho peer --user NAME # Set user peer name
hermes honcho peer --ai NAME # Set AI peer name
hermes honcho peer --reasoning LEVEL # Set dialectic reasoning level
hermes honcho mode # Show current memory mode
hermes honcho mode [hybrid|honcho|local] # Set memory mode
hermes honcho mode [hybrid|honcho] # Set memory mode
hermes honcho tokens # Show token budget settings
hermes honcho tokens --context N # Set context token cap
hermes honcho tokens --dialectic N # Set dialectic char cap