Skip to content

Two hook callbacks have signature mismatches vs Hermes hook API — log flooding + dispatch-path exception #52

Description

@ddfp777

Bug 1: transform_terminal_output — log flooding on every terminal call

Hook: transform_terminal_output
File: clawmes/hooks/transform_terminal_output.py (line 21)
Severity: Log flooding — fires on EVERY terminal call

Root Cause

Hermes invokes the hook with keyword-only arguments. From hermes-agent/tools/terminal_tool.py:2691-2698:

invoke_hook(
    "transform_terminal_output",
    command=command,
    output=output,        # ← keyword arg "output", NOT "text"
    returncode=returncode,
    task_id=effective_task_id or "",
    env_type=env_type,
)

The callback signature declares text as a required positional parameter — it never receives it:

def callback(text: str, **kwargs: Any) -> str:  # ← "text" never filled

Error (from ~/.hermes/logs/errors.log)

2026-07-11 11:24:37 WARNING hermes_cli.plugins: Hook 'transform_terminal_output' callback callback raised:
    callback() missing 1 required positional argument: 'text'

27 occurrences across multiple gateway sessions.

Tested Fix

-def callback(text: str, **kwargs: Any) -> str:
+def callback(output: str, **kwargs: Any) -> str:
     """Return ``text`` with sensitive substrings redacted."""
-    if not text:
-        return text
+    if not output:
+        return output
     try:
-        return scan_and_redact(text, context="terminal_output")
+        return scan_and_redact(output, context="terminal_output")
     except Exception:
         _log.exception("...")
-        return text
+        return output

Bug 2: pre_gateway_dispatch — AttributeError in dispatch path

Hook: pre_gateway_dispatch
File: clawmes/hooks/pre_gateway_dispatch.py (lines 33-38, 46-49)
Severity: Dispatch-path exception — observed during gateway INTERNAL_BUG crash

Root Cause

Hermes' VALID_HOOKS docstring (plugins.py:172) specifies:

# Kwargs: event: MessageEvent, gateway: GatewayRunner, session_store.

MessageEvent is a @dataclass (gateway/platforms/base.py:1715):

@dataclass
class MessageEvent:
    text: str
    message_type: MessageType = MessageType.TEXT
    source: SessionSource = None          # ← NOT "from"
    raw_message: Any = None
    message_id: Optional[str] = None

The callback declares event: dict[str, Any] and calls .get() — two errors:

  1. MessageEvent is a dataclass, not a dict — no .get() method
  2. Field names are wrong: "from" → should be source, "content" → should be text

Error (from ~/.hermes/logs/errors.log)

2026-07-11 10:30:29 WARNING hermes_cli.plugins: Hook 'pre_gateway_dispatch' callback callback raised:
    'MessageEvent' object has no attribute 'get'

3 occurrences during gateway crash window.

Tested Fix

-from typing import Any
+from typing import Any, TYPE_CHECKING
+
+if TYPE_CHECKING:
+    from gateway.platforms.base import MessageEvent

 from clawmes.lib.logger import logger_for

 _log = logger_for("hooks.pre_gateway_dispatch")


 def callback(
     *,
-    event: dict[str, Any] | None = None,
+    event: "MessageEvent | None" = None,
     gateway: Any = None,
     session_store: Any = None,
     **kwargs: Any,
 ) -> dict[str, str] | None:
     """Inbound message interceptor."""
     if event is None:
         return None
     _log.debug(
         "pre_gateway_dispatch: from=%s text_len=%d",
-        event.get("from"),
-        len(event.get("content") or ""),
+        getattr(event, "source", None),
+        len(getattr(event, "text", None) or ""),
     )
     return None

Reproduction

  • clawmes: HEAD 75e4478 / v0.19.0
  • Hermes Agent: gateway mode, any platform
  • Trigger: Any terminal command (Bug 1), any inbound message (Bug 2)

Environment

  • Windows 10
  • Python 3.11.15
  • Hermes gateway with clawmes plugin enabled

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions