feat(honcho): context injection overhaul, 5-tool surface, cost safety, session isolation (#10619)
Salvaged from PR #9884 by erosika. Cherry-picked plugin changes onto
current main with minimal core modifications.
Plugin changes (plugins/memory/honcho/):
- New honcho_reasoning tool (5th tool, splits LLM calls from honcho_context)
- Two-layer context injection: base context (summary + representation + card)
on contextCadence, dialectic supplement on dialecticCadence
- Multi-pass dialectic depth (1-3 passes) with early bail-out on strong signal
- Cold/warm prompt selection based on session state
- dialecticCadence defaults to 3 (was 1) — ~66% fewer Honcho LLM calls
- Session summary injection for conversational continuity
- Bidirectional peer targeting on all 5 tools
- Correctness fixes: peer param fallback, None guard on set_peer_card,
schema validation, signal_sufficient anchored regex, mid->medium level fix
Core changes (~20 lines across 3 files):
- agent/memory_manager.py: Enhanced sanitize_context() to strip full
<memory-context> blocks and system notes (prevents leak from saveMessages)
- run_agent.py: gateway_session_key param for stable per-chat Honcho sessions,
on_turn_start() call before prefetch_all() for cadence tracking,
sanitize_context() on user messages to strip leaked memory blocks
- gateway/run.py: skip_memory=True on 2 temp agents (prevents orphan sessions),
gateway_session_key threading to main agent
Tests: 509 passed (3 skipped — honcho SDK not installed locally)
Docs: Updated honcho.md, memory-providers.md, tools-reference.md, SKILL.md
Co-authored-by: erosika <erosika@users.noreply.github.com>
2026-04-15 19:12:19 -07:00
|
|
|
"""Tests for plugins/memory/honcho/cli.py."""
|
|
|
|
|
|
|
|
|
|
from types import SimpleNamespace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestCmdStatus:
|
|
|
|
|
def test_reports_connection_failure_when_session_setup_fails(self, monkeypatch, capsys, tmp_path):
|
|
|
|
|
import plugins.memory.honcho.cli as honcho_cli
|
|
|
|
|
|
|
|
|
|
cfg_path = tmp_path / "honcho.json"
|
|
|
|
|
cfg_path.write_text("{}")
|
|
|
|
|
|
|
|
|
|
class FakeConfig:
|
|
|
|
|
enabled = True
|
|
|
|
|
api_key = "root-key"
|
|
|
|
|
workspace_id = "hermes"
|
|
|
|
|
host = "hermes"
|
|
|
|
|
base_url = None
|
|
|
|
|
ai_peer = "hermes"
|
|
|
|
|
peer_name = "eri"
|
|
|
|
|
recall_mode = "hybrid"
|
|
|
|
|
user_observe_me = True
|
|
|
|
|
user_observe_others = False
|
|
|
|
|
ai_observe_me = False
|
|
|
|
|
ai_observe_others = True
|
|
|
|
|
write_frequency = "async"
|
|
|
|
|
session_strategy = "per-session"
|
|
|
|
|
context_tokens = 800
|
feat(honcho): dialectic liveness — stale-thread watchdog, stale-result discard, empty-streak backoff
Hardens the dialectic lifecycle against three failure modes that could
leave the prefetch pipeline stuck or injecting stale content:
- Stale-thread watchdog: _thread_is_live() treats any prefetch thread
older than timeout × 2.0 as dead. A hung Honcho call can no longer
block subsequent fires indefinitely.
- Stale-result discard: pending _prefetch_result is tagged with its
fire turn. prefetch() discards the result if more than cadence × 2
turns passed before a consumer read it (e.g. a run of trivial-prompt
turns between fire and read).
- Empty-streak backoff: consecutive empty dialectic returns widen the
effective cadence (dialectic_cadence + streak, capped at cadence × 8).
A healthy fire resets the streak. Prevents the plugin from hammering
the backend every turn when the peer graph is cold.
- liveness_snapshot() on the provider exposes current turn, last fire,
pending fire-at, empty streak, effective cadence, and thread status
for in-process diagnostics.
- system_prompt_block: nudge the model that honcho_reasoning accepts
reasoning_level minimal/low/medium/high/max per call.
- hermes honcho status: surface base reasoning level, cap, and heuristic
toggle so config drift is visible at a glance.
Tests: 550 passed.
- TestDialecticLiveness (8 tests): stale-thread recovery, stale-result
discard, fresh-result retention, backoff widening, backoff ceiling,
streak reset on success, streak increment on empty, snapshot shape.
- Existing TestDialecticCadenceAdvancesOnSuccess::test_in_flight_thread_is_not_stacked
updated to set _prefetch_thread_started_at so it tests the
fresh-thread-blocks branch (stale path covered separately).
- test_cli TestCmdStatus fake updated with the new config attrs surfaced
in the status block.
2026-04-18 13:07:09 -04:00
|
|
|
dialectic_reasoning_level = "low"
|
|
|
|
|
reasoning_level_cap = "high"
|
|
|
|
|
reasoning_heuristic = True
|
feat(honcho): context injection overhaul, 5-tool surface, cost safety, session isolation (#10619)
Salvaged from PR #9884 by erosika. Cherry-picked plugin changes onto
current main with minimal core modifications.
Plugin changes (plugins/memory/honcho/):
- New honcho_reasoning tool (5th tool, splits LLM calls from honcho_context)
- Two-layer context injection: base context (summary + representation + card)
on contextCadence, dialectic supplement on dialecticCadence
- Multi-pass dialectic depth (1-3 passes) with early bail-out on strong signal
- Cold/warm prompt selection based on session state
- dialecticCadence defaults to 3 (was 1) — ~66% fewer Honcho LLM calls
- Session summary injection for conversational continuity
- Bidirectional peer targeting on all 5 tools
- Correctness fixes: peer param fallback, None guard on set_peer_card,
schema validation, signal_sufficient anchored regex, mid->medium level fix
Core changes (~20 lines across 3 files):
- agent/memory_manager.py: Enhanced sanitize_context() to strip full
<memory-context> blocks and system notes (prevents leak from saveMessages)
- run_agent.py: gateway_session_key param for stable per-chat Honcho sessions,
on_turn_start() call before prefetch_all() for cadence tracking,
sanitize_context() on user messages to strip leaked memory blocks
- gateway/run.py: skip_memory=True on 2 temp agents (prevents orphan sessions),
gateway_session_key threading to main agent
Tests: 509 passed (3 skipped — honcho SDK not installed locally)
Docs: Updated honcho.md, memory-providers.md, tools-reference.md, SKILL.md
Co-authored-by: erosika <erosika@users.noreply.github.com>
2026-04-15 19:12:19 -07:00
|
|
|
|
|
|
|
|
def resolve_session_name(self):
|
|
|
|
|
return "hermes"
|
|
|
|
|
|
|
|
|
|
monkeypatch.setattr(honcho_cli, "_read_config", lambda: {"apiKey": "***"})
|
|
|
|
|
monkeypatch.setattr(honcho_cli, "_config_path", lambda: cfg_path)
|
|
|
|
|
monkeypatch.setattr(honcho_cli, "_local_config_path", lambda: cfg_path)
|
|
|
|
|
monkeypatch.setattr(honcho_cli, "_active_profile_name", lambda: "default")
|
|
|
|
|
monkeypatch.setattr(
|
|
|
|
|
"plugins.memory.honcho.client.HonchoClientConfig.from_global_config",
|
|
|
|
|
lambda host=None: FakeConfig(),
|
|
|
|
|
)
|
|
|
|
|
monkeypatch.setattr(
|
|
|
|
|
"plugins.memory.honcho.client.get_honcho_client",
|
|
|
|
|
lambda cfg: object(),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def _boom(hcfg, client):
|
|
|
|
|
raise RuntimeError("Invalid API key")
|
|
|
|
|
|
|
|
|
|
monkeypatch.setattr(honcho_cli, "_show_peer_cards", _boom)
|
|
|
|
|
monkeypatch.setitem(__import__("sys").modules, "honcho", SimpleNamespace())
|
|
|
|
|
|
|
|
|
|
honcho_cli.cmd_status(SimpleNamespace(all=False))
|
|
|
|
|
|
|
|
|
|
out = capsys.readouterr().out
|
|
|
|
|
assert "FAILED (Invalid API key)" in out
|
|
|
|
|
assert "Connection... OK" not in out
|