aboutsummaryrefslogtreecommitdiff
path: root/src/integration/assets
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-19 00:23:20 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-19 00:26:05 +0300
commite7f94a3f359fe1be94a0863b731d94d245093848 (patch)
treef89459235e9a163bbafc68fb485d9355b6fd1e3f /src/integration/assets
parent19295b85e5d6c2c7a9bce5d52343d89749d9f628 (diff)
feat: support hermes agent integration
refs #144
Diffstat (limited to 'src/integration/assets')
-rw-r--r--src/integration/assets/hermes/__init__.py97
-rw-r--r--src/integration/assets/hermes/plugin.yaml3
2 files changed, 100 insertions, 0 deletions
diff --git a/src/integration/assets/hermes/__init__.py b/src/integration/assets/hermes/__init__.py
new file mode 100644
index 00000000..03d15a55
--- /dev/null
+++ b/src/integration/assets/hermes/__init__.py
@@ -0,0 +1,97 @@
+"""Hermes plugin installed by Herdr to report agent lifecycle state."""
+
+# HERDR_INTEGRATION_ID=hermes
+# HERDR_INTEGRATION_VERSION=1
+
+from __future__ import annotations
+
+import json
+import os
+import random
+import socket
+import time
+
+_SOURCE = "herdr:hermes"
+_AGENT = "hermes"
+
+
+def _base_params() -> tuple[str, str] | None:
+ if os.environ.get("HERDR_ENV") != "1":
+ return None
+ pane_id = os.environ.get("HERDR_PANE_ID", "").strip()
+ socket_path = os.environ.get("HERDR_SOCKET_PATH", "").strip()
+ if not pane_id or not socket_path:
+ return None
+ return pane_id, socket_path
+
+
+def _send(method: str, params: dict) -> None:
+ base = _base_params()
+ if base is None:
+ return
+ pane_id, socket_path = base
+ params = {
+ "pane_id": pane_id,
+ "source": _SOURCE,
+ "agent": _AGENT,
+ "seq": time.time_ns(),
+ **params,
+ }
+ request = {
+ "id": f"{_SOURCE}:{int(time.time() * 1000)}:{random.randrange(1_000_000):06d}",
+ "method": method,
+ "params": params,
+ }
+ try:
+ client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ client.settimeout(0.5)
+ client.connect(socket_path)
+ client.sendall((json.dumps(request) + "\n").encode("utf-8"))
+ try:
+ client.recv(4096)
+ except Exception:
+ pass
+ client.close()
+ except Exception:
+ pass
+
+
+def _report(state: str) -> None:
+ _send("pane.report_agent", {"state": state})
+
+
+def _release() -> None:
+ _send("pane.release_agent", {})
+
+
+def _working(**kwargs) -> None:
+ del kwargs
+ _report("working")
+
+
+def _blocked(**kwargs) -> None:
+ del kwargs
+ _report("blocked")
+
+
+def _idle(**kwargs) -> None:
+ del kwargs
+ _report("idle")
+
+
+def _finalize(**kwargs) -> None:
+ del kwargs
+ _release()
+
+
+def register(ctx):
+ ctx.register_hook("on_session_start", _idle)
+ ctx.register_hook("pre_llm_call", _working)
+ ctx.register_hook("pre_api_request", _working)
+ ctx.register_hook("pre_tool_call", _working)
+ ctx.register_hook("post_tool_call", _working)
+ ctx.register_hook("pre_approval_request", _blocked)
+ ctx.register_hook("post_approval_response", _working)
+ ctx.register_hook("post_llm_call", _idle)
+ ctx.register_hook("on_session_end", _idle)
+ ctx.register_hook("on_session_finalize", _finalize)
diff --git a/src/integration/assets/hermes/plugin.yaml b/src/integration/assets/hermes/plugin.yaml
new file mode 100644
index 00000000..282f3b34
--- /dev/null
+++ b/src/integration/assets/hermes/plugin.yaml
@@ -0,0 +1,3 @@
+name: herdr-agent-state
+version: "1.0"
+description: Report Hermes Agent lifecycle state to Herdr panes