Skip to content

fix(hermes): declare all plugin hooks#486

Merged
rohitg00 merged 2 commits into
rohitg00:mainfrom
honor2030:fix/hermes-plugin-hooks-478
May 19, 2026
Merged

fix(hermes): declare all plugin hooks#486
rohitg00 merged 2 commits into
rohitg00:mainfrom
honor2030:fix/hermes-plugin-hooks-478

Conversation

@honor2030
Copy link
Copy Markdown
Contributor

@honor2030 honor2030 commented May 18, 2026

Summary

  • Declare all Hermes lifecycle hooks implemented by AgentMemoryProvider in integrations/hermes/plugin.yaml.
  • Add a manifest regression test so the Hermes hook list cannot silently drift from the provider implementation again.

Why

AgentMemoryProvider already implements prefetch, sync_turn, and system_prompt_block, and the Hermes README documents them. The plugin manifest only declared on_session_end, on_pre_compress, and on_memory_write, so Hermes may never invoke the missing lifecycle hooks. That can silently disable context prefetching, turn capture, and system-prompt context injection for Hermes users.

Closes #478.

Conflict / duplicate check

  • Checked open PRs touching integrations/hermes/plugin.yaml, integrations/hermes/__init__.py, or test/hermes-plugin.test.ts: none found.
  • This PR only changes the Hermes plugin manifest plus a focused drift test; it does not change AgentMemory server/runtime behavior.

Test plan

  • RED: PATH=/opt/homebrew/bin:$PATH npm test -- test/hermes-plugin.test.ts --reporter=verbose
    • failed on current main because the manifest only declared on_session_end, on_pre_compress, and on_memory_write.
  • GREEN: PATH=/opt/homebrew/bin:$PATH npm test -- test/hermes-plugin.test.ts --reporter=verbose
    • 1 passed
  • Relevant guard: PATH=/opt/homebrew/bin:$PATH npm test -- test/hermes-plugin.test.ts test/integration-plaintext-http.test.ts --reporter=verbose
    • 14 passed
  • Full suite: PATH=/opt/homebrew/bin:$PATH npm test -- --reporter=dot
    • 92 passed, 1008 passed
  • Build: PATH=/opt/homebrew/bin:$PATH npm run build
    • completed successfully
  • git diff --check
    • clean

Note: local shell defaulted to Node 16, so I used Homebrew Node v23.11.0 on PATH for the repo's Node >=20 toolchain.

Summary by CodeRabbit

  • New Features

    • Extended Hermes plugin integration with additional lifecycle hooks to enable more flexible plugin behavior and richer interactions during session and sync flows.
  • Tests

    • Added a validation test suite to ensure the plugin manifest stays consistent with the implemented hooks and preserves expected hook ordering.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 18, 2026

@honor2030 is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6207c80-0c84-431e-a0ac-6f769fb2fa58

📥 Commits

Reviewing files that changed from the base of the PR and between 4c747c9 and bf8c65d.

📒 Files selected for processing (1)
  • test/hermes-plugin.test.ts

📝 Walkthrough

Walkthrough

Updated Hermes plugin manifest to declare all six lifecycle hooks (prefetch, sync_turn, on_session_end, on_pre_compress, on_memory_write, system_prompt_block) and added a Vitest that verifies the YAML hook list matches the expected order and the Python implementation.

Changes

Hermes Plugin Hook Declarations

Layer / File(s) Summary
Plugin manifest and consistency validation
integrations/hermes/plugin.yaml, test/hermes-plugin.test.ts
Plugin manifest now declares all 6 hooks including prefetch, sync_turn, and system_prompt_block. New Vitest suite validates YAML declarations match the expected hook list in order and that Python-implemented hooks contain all expected ones.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • rohitg00/agentmemory#107: The main PR updates integrations/hermes/plugin.yaml (and adds a consistency test) to declare the same additional hook names (prefetch, sync_turn, system_prompt_block) that integrations/hermes/__init__.py already implements in the retrieved PR, so the changes directly align at the hook/manifest level.
  • rohitg00/agentmemory#384: The main PR expands the Hermes plugin manifest to include the sync_turn lifecycle hook, and the retrieved PR fixes the sync_turn() payload keys in integrations/hermes/__init__.py to match the server API—so the manifest and the sync_turn implementation are directly connected.
  • rohitg00/agentmemory#252: The main PR's updated Hermes plugin.yaml (and its test expecting prefetch/sync_turn hooks) aligns with the retrieved PR's Hermes memory-provider hook changes that make prefetch and sync_turn (and others) accept extra **kwargs, ensuring those newly declared hooks match runnable method contracts.

Poem

🐰 I hopped through YAML to make hooks align,
I checked Python lines to ensure each sign,
Prefetch and sync_turn joined the show,
system_prompt_block now in the flow,
A little test made manifest and code combine.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(hermes): declare all plugin hooks' accurately summarizes the main change of declaring all six implemented Hermes lifecycle hooks in the plugin manifest.
Linked Issues check ✅ Passed The PR fully addresses issue #478 by declaring all six hooks (prefetch, sync_turn, on_session_end, on_pre_compress, on_memory_write, system_prompt_block) in plugin.yaml and adding a regression test to prevent drift.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the declared hooks issue: updating plugin.yaml and adding a focused regression test. No extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
test/hermes-plugin.test.ts (2)

13-32: ⚖️ Poor tradeoff

Consider using a YAML parser library.

The manual line-by-line parsing works for the simple plugin.yaml structure but is fragile to YAML features like comments, multi-line values, or anchors. While acceptable for this focused test, a proper YAML parser (e.g., js-yaml) would be more robust.

📦 Example using js-yaml
+import yaml from "js-yaml";
+
 function readHermesPluginHooks(): string[] {
-  const manifest = readFileSync("integrations/hermes/plugin.yaml", "utf8");
-  const hooks: string[] = [];
-  let inHooks = false;
-
-  for (const line of manifest.split(/\r?\n/)) {
-    if (line.trim() === "hooks:") {
-      inHooks = true;
-      continue;
-    }
-    if (!inHooks) continue;
-    if (line.trim() === "") continue;
-    if (!line.startsWith(" ")) break;
-
-    const match = line.match(/^\s*-\s*([A-Za-z_][A-Za-z0-9_]*)\s*$/);
-    if (match) hooks.push(match[1]);
-  }
-
-  return hooks;
+  const content = readFileSync("integrations/hermes/plugin.yaml", "utf8");
+  const manifest = yaml.load(content) as { hooks?: string[] };
+  return manifest.hooks || [];
 }

Requires adding js-yaml and @types/js-yaml to dev dependencies.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/hermes-plugin.test.ts` around lines 13 - 32, Replace the fragile manual
parser in readHermesPluginHooks with a proper YAML parser: import and use
js-yaml to read and parse "integrations/hermes/plugin.yaml", then extract the
"hooks" key from the parsed object, validate it's an array of strings and return
it; ensure the new implementation handles missing/invalid hooks by returning an
empty array or throwing a clear error and update any types accordingly
(reference function name readHermesPluginHooks and the "hooks" field in
plugin.yaml).

38-38: ⚡ Quick win

Regex fragile to indentation changes.

The pattern /^ def .../ assumes exactly 4 spaces. If the Python file is reformatted with different indentation (tabs, 2 spaces, etc.), the regex breaks.

♻️ More flexible indentation pattern
-  const hookMethodPattern =
-    /^    def (prefetch|sync_turn|on_session_end|on_pre_compress|on_memory_write|system_prompt_block)\(/gm;
+  const hookMethodPattern =
+    /^\s+def (prefetch|sync_turn|on_session_end|on_pre_compress|on_memory_write|system_prompt_block)\(/gm;

Using \s+ matches any indentation (spaces or tabs).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/hermes-plugin.test.ts` at line 38, The regex /^    def
(prefetch|sync_turn|on_session_end|on_pre_compress|on_memory_write|system_prompt_block)\(/gm
is brittle because it requires exactly four spaces; update it to allow any
whitespace indentation by using /^\s+def
(prefetch|sync_turn|on_session_end|on_pre_compress|on_memory_write|system_prompt_block)\(/gm
(keep the same flags), then run tests to ensure matches for the listed function
names still work across tabs/2-space/4-space formatting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/hermes-plugin.test.ts`:
- Around line 34-54: The test currently limits discovery to six hardcoded names
via hookMethodPattern in readAgentMemoryProviderHookMethods which allows YAML
drift; change readAgentMemoryProviderHookMethods to use a general method regex
(e.g., /^    def (\w+)\(/gm) to collect all method names defined in
integrations/hermes/__init__.py (specifically methods on the AgentMemoryProvider
implementation), then filter those names for valid Hermes hook patterns (e.g.,
names that match the Hermes hook naming convention or a small predicate), and
finally replace the current partial assertions so the test asserts exact
equality between the discovered Python hooks and the YAML-declared hooks from
readHermesPluginHooks (instead of comparing against expectedHermesHooks) to
ensure no drift.

---

Nitpick comments:
In `@test/hermes-plugin.test.ts`:
- Around line 13-32: Replace the fragile manual parser in readHermesPluginHooks
with a proper YAML parser: import and use js-yaml to read and parse
"integrations/hermes/plugin.yaml", then extract the "hooks" key from the parsed
object, validate it's an array of strings and return it; ensure the new
implementation handles missing/invalid hooks by returning an empty array or
throwing a clear error and update any types accordingly (reference function name
readHermesPluginHooks and the "hooks" field in plugin.yaml).
- Line 38: The regex /^    def
(prefetch|sync_turn|on_session_end|on_pre_compress|on_memory_write|system_prompt_block)\(/gm
is brittle because it requires exactly four spaces; update it to allow any
whitespace indentation by using /^\s+def
(prefetch|sync_turn|on_session_end|on_pre_compress|on_memory_write|system_prompt_block)\(/gm
(keep the same flags), then run tests to ensure matches for the listed function
names still work across tabs/2-space/4-space formatting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6accfccd-e7e1-497f-8cc5-e5c86367b978

📥 Commits

Reviewing files that changed from the base of the PR and between 9061da5 and 4c747c9.

📒 Files selected for processing (2)
  • integrations/hermes/plugin.yaml
  • test/hermes-plugin.test.ts

Comment thread test/hermes-plugin.test.ts
@rohitg00 rohitg00 mentioned this pull request May 19, 2026
@rohitg00 rohitg00 merged commit c1c2c3a into rohitg00:main May 19, 2026
3 of 4 checks passed
@rohitg00
Copy link
Copy Markdown
Owner

Merged + shipping in next release. Thanks @honor2030 — Hermes plugin manifest now declares all 6 hooks (prefetch, sync_turn, on_session_end, on_pre_compress, on_memory_write, system_prompt_block) instead of just 3.

@rohitg00 rohitg00 mentioned this pull request May 19, 2026
rohitg00 added a commit that referenced this pull request May 19, 2026
Quality + integration wave. Bundles 11 PRs since v0.9.20:

Contributor feature:
- #237 OpenCode plugin with 22 auto-capture hooks (@cl0ckt0wer)

Bug fixes (9):
- #516 memory_recall endpoint + format/token_budget (@serhiizghama, closes #507/#440)
- #461 env-file AGENTMEMORY_DROP_STALE_INDEX flag honored (@honor2030, closes #456)
- #487 Windows hook path quoting (@honor2030, closes #477)
- #517 viewer IME composition guard (@jonathanzhan1975)
- #472 chunk large sessions for LLM context window (@efenex)
- #473 surface lessons in smart-search + diagnose tally (@efenex)
- #486 declare all Hermes plugin hooks (@honor2030)
- #500 rebuildIndex non-blocking on boot (@efenex)
- #504 batched embed in rebuildIndex (25h -> 3h) (@efenex)
- #491 cli skip onboarding without tty (@honor2030)

Upstream-installer revert:
- #546 drop --next workaround now that iii-hq/iii#1660 shipped

1067/1067 tests pass across 95 files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hermes plugin.yaml declares only 3 of 6 implemented hooks — missing prefetch, sync_turn, system_prompt_block

2 participants