feat: pluggable context engine slot + unified hermes plugins UI#7464
Merged
Conversation
…om it Introduces agent/context_engine.py — an abstract base class that defines the pluggable context engine interface. ContextCompressor now inherits from ContextEngine as the default implementation. No behavior change. All 34 existing compressor tests pass. This is the foundation for a context engine plugin slot, enabling third-party engines like LCM (Lossless Context Management) to replace the built-in compressor via the plugin system.
- PluginContext.register_context_engine() lets plugins replace the built-in ContextCompressor with a custom ContextEngine implementation - PluginManager stores the registered engine; only one allowed - run_agent.py checks for a plugin engine at init before falling back to the default ContextCompressor - reset_session_state() now calls engine.on_session_reset() instead of poking internal attributes directly - ContextCompressor.on_session_reset() handles its own internals (_context_probed, _previous_summary, etc.) - 19 new tests covering ABC contract, defaults, plugin slot registration, rejection of duplicates/non-engines, and compressor reset behavior - All 34 existing compressor tests pass unchanged
- Inject engine tool schemas into agent tool surface after compressor init - Call on_session_start() with session_id, hermes_home, platform, model - Dispatch engine tool calls (lcm_grep, etc.) before regular tool handler - 55/55 tests pass
…very, ABC completeness Follow-up fixes for the context engine plugin slot (PR #5700): - Enhance ContextEngine ABC: add threshold_percent, protect_first_n, protect_last_n as class attributes; complete update_model() default with threshold recalculation; clarify on_session_end() lifecycle docs - Add ContextCompressor.update_model() override for model/provider/ base_url/api_key updates - Replace all direct compressor internal access in run_agent.py with ABC interface: switch_model(), fallback restore, context probing all use update_model() now; _context_probed guarded with getattr/ hasattr for plugin engine compatibility - Create plugins/context_engine/ directory with discovery module (mirrors plugins/memory/ pattern) — discover_context_engines(), load_context_engine() - Add context.engine config key to DEFAULT_CONFIG (default: compressor) - Config-driven engine selection in run_agent.__init__: checks config, then plugins/context_engine/<name>/, then general plugin system, falls back to built-in ContextCompressor - Wire on_session_end() in shutdown_memory_provider() at real session boundaries (CLI exit, /reset, gateway expiry)
…egories - Remove auto-activation: when context.engine is 'compressor' (default), plugin-registered engines are NOT used. Users must explicitly set context.engine to a plugin name to activate it. - Add curses_radiolist() to curses_ui.py: single-select radio picker with keyboard nav + text fallback, matching curses_checklist pattern. - Rewrite cmd_toggle() as composite plugins UI: Top section: general plugins with checkboxes (existing behavior) Bottom section: provider plugin categories (Memory Provider, Context Engine) with current selection shown inline. ENTER/SPACE on a category opens a radiolist sub-screen for single-select configuration. - Add provider discovery helpers: _discover_memory_providers(), _discover_context_engines(), config read/save for memory.provider and context.engine. - Add tests: radiolist non-TTY fallback, provider config save/load, discovery error handling, auto-activation removal verification.
New page: - developer-guide/context-engine-plugin.md — full guide for building context engine plugins (ABC contract, lifecycle, tools, registration) Updated pages (11 files): - plugins.md — plugin types table, composite UI documentation with screenshot-style example, provider plugin config format - cli-commands.md — hermes plugins section rewritten for composite UI with provider plugin config keys documented - context-compression-and-caching.md — new 'Pluggable Context Engine' section explaining the ABC, config-driven selection, resolution order - configuration.md — new 'Context Engine' config section with examples - architecture.md — context_engine.py and plugins/context_engine/ added to directory trees, plugin system description updated - memory-provider-plugin.md — cross-reference tip to context engines - memory-providers.md — hermes plugins as alternative setup path - agent-loop.md — context_engine.py added to file reference table - overview.md — plugins description expanded to cover all 3 types - build-a-hermes-plugin.md — tip box linking to specialized plugin guides - sidebars.ts — context-engine-plugin added to Extending category
This was referenced Apr 11, 2026
2 tasks
Contributor
|
@teknium1 sorry to bother, but as this was cherry picked, I started working with it and some bugs I helped patching (which have been merged into Hermes-LCM repository by @stephenschoettler ), need some extra support from Hermes Agent. I know you are a very busy person, but would you be able to eyeball this PR quickly to help LCM a bit better? #8416 |
ccross2
added a commit
to ccross2/hermes-agent
that referenced
this pull request
Apr 14, 2026
Brings ccross2/hermes-agent up to NousResearch/hermes-agent@ac80bd61 (v0.9.0 release "the everywhere release"). Merge highlights from upstream: - Pluggable Context Engine slot (NousResearch#7464) - Local web dashboard, Termux/Android, iMessage/WeChat platforms - Fast Mode (/fast) for OpenAI/Anthropic priority queues - Background process monitoring (watch_patterns, NousResearch#7635) - Comprehensive security hardening (Twilio signature, SSRF, path traversal, git injection, shell injection in sandbox writes) - Dead code cleanup (1,784 lines across 77 files, NousResearch#9180) - CANONICAL_PROVIDERS consolidation (NousResearch#9237) - gateway /stop no longer resets session (NousResearch#9224) Conflict resolution summary (7 hunks across 3 files): 1-4. cli.py _build_compact_banner — took upstream. Upstream added skin-aware colors + version label + tiny_line for narrow terminals. ccross2 had added word-wrapping for narrow terminals (commit 5b32504). The skin engine integration is foundational (affects several other surfaces); the word-wrapping improvement can be re-added as a follow-up on top of skin-aware. 5. cli.py _reset_stream_state — kept BOTH. ccross2 added _stream_in_code_fence; upstream added _deferred_content. Different features in the same reset hook, both needed. 6. tools/transcription_tools.py get_stt_model_from_config — took ccross2. ccross2 added provider-aware model resolution (local/groq/openai with per-provider model overrides). Upstream restructured but didn't provide an equivalent; the function coexists with upstream's _load_stt_config() which returns the raw dict. 7. tests/tools/test_transcription_tools.py — took ccross2. Tests for the provider-aware function we kept in (6). Post-merge state: 5 local ccross2 commits preserved on top of upstream 0.9. Backup of pre-merge state at ccross2/cc-fusion-09-rebase-backup (Claude Code's rebase attempt with 4 of the 5 patches, before this proper merge). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Salvages PR #6126 (which salvaged PR #5700 by @stephenschoettler) and adds the unified
hermes pluginsUI with provider plugin categories.From PR #6126 / #5700 (cherry-picked, credit: @stephenschoettler)
agent/context_engine.py— ContextEngine ABC with lifecycle hooks, tool schemas, model switch supportagent/context_compressor.py— Now inherits from ContextEngine ABC, addson_session_reset(),update_model(),namepropertyhermes_cli/plugins.py—register_context_engine()on PluginContext, single-engine enforcementhermes_cli/config.py—context.enginein DEFAULT_CONFIG, "context" in _KNOWN_TOP_LEVELplugins/context_engine/__init__.py— Discovery module mirroring memory pluginsrun_agent.py— Config-driven engine selection, tool injection/dispatch, ABC calls throughout, session lifecycle wiringtests/agent/test_context_engine.py— 19 tests for ABC contract, plugin slotFollow-up fixes (this PR adds)
No auto-activation (policy fix):
When
context.engineis"compressor"(default), plugin-registered engines are NOT used. Users must explicitly setcontext.engineto a plugin's name in config.yaml to activate it. This prevents silently overriding the built-in compressor just by installing a plugin.Unified
hermes pluginsUI:curses_radiolist()incurses_ui.py— single-select radio picker with keyboard nav + text fallbackcmd_toggle()screen combining:_discover_memory_providers(),_discover_context_engines()_save_memory_provider(),_save_context_engine()Tests:
Subsumes
Closes #5701. Credit to @stephenschoettler for the original design and implementation.