feat(honcho): declare identity_signature and drop the gateway's honcho keys

The gateway agent cache read honcho.json itself through a honcho-named
block in gateway/run.py and gateway/run_agent_cache.py. Every other memory
provider had no way to bust the cache when its identity mapping changed.

HonchoMemoryProvider.identity_signature() now returns the same values under
provider-neutral keys: user_identity, agent_identity, pin_user_identity,
runtime_identity_prefix, user_identity_aliases, session_prefixing. The
gateway files them under memory.<key> through the MemoryProvider hook. The
hook reads config only, memoizes on the file's mtime and size, and returns
an empty dict when the file cannot be read.

The honcho-specific extractor, its memo and its key tuple are gone from the
gateway. The pinPeerName cache-busting test now asserts on
memory.pin_user_identity.
This commit is contained in:
Erosika
2026-09-04 15:33:57 -04:00
committed by Teknium
parent 46d625b097
commit 88fc9402d8
5 changed files with 126 additions and 42 deletions
+1 -34
View File
@@ -42,34 +42,6 @@ def _tuple_agent(entry: Any) -> Any:
class GatewayAgentCacheMixin:
"""Agent cache, session model overrides, turn leases, run generations and conversation-scope reset for GatewayRunner."""
@classmethod
def _extract_honcho_cache_busting_config(cls) -> dict[str, Any]:
"""Extract Honcho identity keys, memoized by honcho.json mtime; all-None when unavailable."""
try:
from plugins.memory.honcho.client import HonchoClientConfig, resolve_config_path
path = resolve_config_path()
try:
mtime_ns = path.stat().st_mtime_ns
except OSError:
mtime_ns = None
memo_key = (str(path), mtime_ns)
cached = cls._HONCHO_CACHE_BUSTING_MEMO.get(memo_key)
if cached is not None:
return dict(cached)
hcfg = HonchoClientConfig.from_global_config(config_path=path)
aliases = hcfg.user_peer_aliases or {}
values = {
"honcho.peer_name": hcfg.peer_name,
"honcho.ai_peer": hcfg.ai_peer,
"honcho.pin_peer_name": bool(hcfg.pin_peer_name),
"honcho.runtime_peer_prefix": hcfg.runtime_peer_prefix or "",
"honcho.user_peer_aliases": sorted(aliases.items()) if isinstance(aliases, dict) else [],
}
cls._HONCHO_CACHE_BUSTING_MEMO = {memo_key: values}
return dict(values)
except Exception:
return dict.fromkeys(cls._HONCHO_CACHE_BUSTING_KEYS)
@classmethod
def _extract_cache_busting_config(cls, user_config: dict | None) -> dict:
"""Values that must bust the cached agent, as a flat dict keyed by 'section.key'. Missing keys /
@@ -89,12 +61,7 @@ class GatewayAgentCacheMixin:
out["tools.registry_generation"] = getattr(registry, "_generation", None)
except Exception:
out["tools.registry_generation"] = None
# Honcho identity-mapping keys live in honcho.json, not user_config; only read that file
# when Honcho is the active memory provider.
provider = cfg_get(cfg, "memory", "provider")
honcho = isinstance(provider, str) and provider.lower() == "honcho"
out.update(cls._extract_honcho_cache_busting_config() if honcho else dict.fromkeys(cls._HONCHO_CACHE_BUSTING_KEYS))
for key, value in cls._memory_provider_identity_signature(provider).items():
for key, value in cls._memory_provider_identity_signature(cfg_get(cfg, "memory", "provider")).items():
out[f"memory.{key}"] = value
return out