feat(plugins): add four extension hooks for plugin-directed core behavior - #74645
Closed
TurgutKural wants to merge 2 commits into
Closed
feat(plugins): add four extension hooks for plugin-directed core behavior#74645TurgutKural wants to merge 2 commits into
TurgutKural wants to merge 2 commits into
Conversation
teknium1
reviewed
Jul 30, 2026
teknium1
left a comment
Contributor
There was a problem hiding this comment.
Thanks for proposing a plugin-surface alternative to the four linked core patches. The target behaviors remain live on current main: agent/agent_runtime_helpers.py:2849 still has unconditional fuzzy fallback, hermes_state.py:2542 and :8322 still issue fixed TRUNCATE checkpoints, tools/delegate_tool.py:3500 has no pre-resolution interception, and agent/conversation_compression.py:1759 invokes the compressor without a pre-hook.
Problems
hermes_state.py’s proposed mode handling accepts every{"mode": ...}value and interpolates it intoPRAGMA wal_checkpoint(...). That contradicts the documented contract that anything except the supported override keeps the default; an invalid mode instead makes the checkpoint fail. The identical parsing appears in the proposedhermes_state_search.pyhunk.tests/hermes_cli/test_extension_hooks.py:165and:196permit the vacuum tests to pass without firing a hook or executing a checkpoint. They also do not cover the modifiedSessionDB.vacuum()path.tests/hermes_cli/test_extension_hooks.py:450-502tests dispatcher return values rather thancompress_context(), so it does not prove the veto branch avoids compressor execution and releases its lease.
Suggested changes
- Validate checkpoint modes against an explicit allow-list and retain
TRUNCATEon every invalid result. - Add deterministic path-level checkpoint tests plus a real compression-veto integration test.
Automated hermes-sweeper review.
TurgutKural
force-pushed
the
feat/plugin-extension-hooks
branch
4 times, most recently
from
August 2, 2026 03:36
03067d6 to
f313e5f
Compare
TurgutKural
force-pushed
the
feat/plugin-extension-hooks
branch
2 times, most recently
from
August 5, 2026 03:47
04d7892 to
e3193bb
Compare
…vior Add pre_db_checkpoint, pre_fuzzy_repair, pre_delegation_credentials, and pre_compression hooks so plugins can override or veto specific core behaviors without patching core files. Motivation: several open PRs (NousResearch#72549, NousResearch#62701, NousResearch#61499, NousResearch#58512) fix real bugs by patching core internals that the plugin system cannot reach. Rather than carrying fork-specific patches across every upstream rebase, expose narrow, fail-open hook points that let a user-installed plugin (~/.hermes/plugins/) implement the same fixes without touching core files. Hook contracts (all fail-open — no plugin loaded = original behavior): - pre_db_checkpoint: fired before WAL checkpoint in SessionDB.close() and pre-VACUUM paths. Return {"mode": "PASSIVE"} to override the default TRUNCATE mode. Enables plugins to prevent page-tear under SIGTERM races (NousResearch#45383) without patching hermes_state.py. - pre_fuzzy_repair: fired before the fuzzy-match fallback in repair_tool_call(). Return {"skip": True} to suppress fuzzy matching for specific tool names (e.g. MCP names where fuzzy substitution changes semantics — NousResearch#62701). - pre_delegation_credentials: fired at the top of _resolve_delegation_credentials(). Return a full credential dict (with "provider" key) to short-circuit built-in resolution. Enables plugins to implement Nous JWT rotation (NousResearch#61499) before the direct-endpoint path runs. - pre_compression: fired just before context compression begins. Return {"skip": True, "reason": str} to veto compression for this tick. Side-effect hooks (e.g. rebinding a shared context engine) may run without returning (NousResearch#58512). Changes: - hermes_cli/plugins.py: add four hooks to VALID_HOOKS with docs - hermes_state.py: fire pre_db_checkpoint in close() and pre-VACUUM - hermes_state_search.py: fire pre_db_checkpoint in optimize VACUUM - agent/agent_runtime_helpers.py: fire pre_fuzzy_repair before fuzzy - tools/delegate_tool.py: fire pre_delegation_credentials at entry - agent/conversation_compression.py: fire pre_compression before start - tests/hermes_cli/test_extension_hooks.py: 26 tests covering all four hooks (default behavior, override, error fallback, kwargs) Validation: - python -m pytest tests/hermes_cli/test_extension_hooks.py → 26 passed - python -m pytest tests/test_wal_checkpoint_strategy.py tests/run_agent/test_repair_tool_call_name.py tests/hermes_cli/test_plugins.py tests/tools/test_delegate.py::TestDelegationCredentialResolution tests/run_agent/test_message_sequence_repair.py → 95 passed - python -m py_compile on all six modified files → OK - Pre-existing failures (No module named 'openai') confirmed identical on unmodified upstream/main — not caused by this change.
…ssion tests - Validate checkpoint mode against (PASSIVE, FULL, RESTART, TRUNCATE); invalid values keep the TRUNCATE default (all 3 call sites) - Vacuum tests now use SessionDB.vacuum() directly instead of optimize_fts_storage() — deterministic, no conditional guard - Added invalid-mode rejection test (SQL injection attempt → TRUNCATE) - Compression tests now exercise compress_context() path-level: veto returns messages unchanged + compressor never called; no-plugin and hook-error paths confirm compressor IS reached
TurgutKural
force-pushed
the
feat/plugin-extension-hooks
branch
from
August 5, 2026 10:26
e3193bb to
ccdaf7f
Compare
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
Add four narrow, fail-open plugin hooks so user-installed plugins (
~/.hermes/plugins/) can override or veto specific core behaviors without patching core files.Motivation
Several open PRs fix real bugs by patching core internals that the plugin system cannot reach:
hermes_state.pyagent/agent_runtime_helpers.pytools/delegate_tool.pyagent/conversation_compression.pyRather than carrying fork-specific patches across every upstream rebase, this PR exposes narrow hook points that let a plugin implement the same fixes without touching core files.
Hook contracts
All hooks are fail-open: no plugin loaded → original behavior preserved exactly. Each call site wraps
invoke_hookin try/except; a misbehaving plugin cannot break the core.pre_db_checkpointFired before WAL checkpoint in
SessionDB.close()and all pre-VACUUM paths (3 call sites).context: "close" | "vacuum",default_mode: str{"mode": "PASSIVE"}to override the checkpoint mode; anything else keeps the default.pre_fuzzy_repairFired before the fuzzy-match fallback in
repair_tool_call().tool_name: str,valid_tool_names: set[str]{"skip": True}to suppress fuzzy matching for this tool name.mcp__*names where substitution changes semantics.pre_delegation_credentialsFired at the top of
_resolve_delegation_credentials()before any built-in resolution.cfg: dict,parent_provider: str|None,parent_model: str|None"provider"key) to short-circuit;Nonefalls through.pre_compressionFired just before context compression begins.
agent,session_id: str,message_count: int{"skip": True, "reason": str}to veto compression for this tick; side-effect hooks (e.g. rebinding a shared context engine) may run without returning.Changes
hermes_cli/plugins.pyVALID_HOOKSwith docstringshermes_state.pypre_db_checkpointinclose()and pre-VACUUMhermes_state_search.pypre_db_checkpointin optimize-storage VACUUMagent/agent_runtime_helpers.pypre_fuzzy_repairbefore fuzzy fallbacktools/delegate_tool.pypre_delegation_credentialsat function entryagent/conversation_compression.pypre_compressionbefore compression startstests/hermes_cli/test_extension_hooks.pyValidation
pytest tests/hermes_cli/test_extension_hooks.py→ 26 passedpytest tests/test_wal_checkpoint_strategy.py tests/run_agent/test_repair_tool_call_name.py tests/hermes_cli/test_plugins.py tests/tools/test_delegate.py::TestDelegationCredentialResolution tests/run_agent/test_message_sequence_repair.py→ 95 passedpython -m py_compileon all six modified files → OKNo module named 'openai') confirmed identical on unmodifiedupstream/main— not caused by this change.Design notes
invoke_hookcontract (list of non-None returns) is sufficient.from hermes_cli.plugins import invoke_hookinside the function body, matching the existing pattern inhermes_state.py(which already lazy-imports fromhermes_cli). No new import cycles.