From 19152ea0fed392e10508259c24a5d79fdb5bcf87 Mon Sep 17 00:00:00 2001 From: jenkins Date: Sun, 9 Aug 2026 01:35:38 -0300 Subject: [PATCH] fix(hermes): install native herdr integration --- services/hermes/agent-deployment.yaml | 40 +++++++++++++++++++++++---- testing/tests/test_hermes_herdr.py | 25 +++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/services/hermes/agent-deployment.yaml b/services/hermes/agent-deployment.yaml index 6e3b8b1e7..f99ca8f11 100644 --- a/services/hermes/agent-deployment.yaml +++ b/services/hermes/agent-deployment.yaml @@ -24,7 +24,7 @@ spec: ai.bstein.dev/execution: Herdr-supervised Codex and Claude Code ai.bstein.dev/model-policy: difficulty-aware low through xhigh, cross-provider fallback ai.bstein.dev/placement: rpi5 preferred; Jetson deferred until state storage is available - ai.bstein.dev/config-rev: "20260808-herdr-browser-tui-prompt-timeout" + ai.bstein.dev/config-rev: "20260809-herdr-hermes-integration" vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/role: hermes-agent vault.hashicorp.com/agent-inject-secret-anthropic-token: kv/data/atlas/hermes/agent-tokens @@ -94,6 +94,9 @@ spec: /opt/data/workspace/coordinator \ /opt/data/workspace/projects \ /opt/data/workspace/skills + if [ ! -e /opt/data/home/.hermes ]; then + ln -s /opt/data /opt/data/home/.hermes + fi cp /config/config.yaml /opt/data/config.yaml cp /config/SOUL.md /opt/data/SOUL.md cp /config/AGENTS.md /opt/data/workspace/AGENTS.md @@ -230,6 +233,33 @@ spec: resources: requests: {cpu: 50m, memory: 128Mi} limits: {cpu: 500m, memory: 512Mi} + - name: install-herdr-integrations + image: registry.bstein.dev/bstein/hermes-agent@sha256:15c5c538c0b58686af2e54e10bc870b23284789d485a609349df24ed3053622f + imagePullPolicy: IfNotPresent + command: + - sh + - -ec + - | + herdr integration install codex + herdr integration install claude + herdr integration install hermes + env: + - {name: HERMES_HOME, value: /opt/data} + - {name: HOME, value: /opt/data/home} + - {name: CODEX_HOME, value: /opt/data/home/.codex} + - {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude} + - {name: PATH, value: /opt/data/tools/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin} + securityContext: + allowPrivilegeEscalation: false + runAsUser: 10000 + runAsGroup: 10000 + seccompProfile: + type: RuntimeDefault + volumeMounts: + - {name: home, mountPath: /opt/data} + resources: + requests: {cpu: 25m, memory: 32Mi} + limits: {cpu: 250m, memory: 128Mi} containers: - name: hermes image: registry.bstein.dev/bstein/hermes-agent@sha256:15c5c538c0b58686af2e54e10bc870b23284789d485a609349df24ed3053622f @@ -246,7 +276,7 @@ spec: - {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude} - {name: HERDR_CONFIG_PATH, value: /opt/data/home/.config/herdr/config.toml} - {name: HERDR_SOCKET_PATH, value: /opt/data/herdr/herdr.sock} - - {name: PATH, value: /opt/data/tools/bin:/opt/data/home/.local/bin:/opt/hermes/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin} + - {name: PATH, value: /opt/data/tools/bin:/opt/data/home/.local/bin:/opt/hermes/.venv/bin:/opt/hermes/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin} - {name: HERMES_DASHBOARD, value: "0"} - {name: HERMES_DASHBOARD_PUBLIC_URL, value: https://agent.hermes.bstein.dev} - {name: API_SERVER_ENABLED, value: "true"} @@ -367,7 +397,7 @@ spec: - {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude} - {name: HERDR_CONFIG_PATH, value: /opt/data/home/.config/herdr/config.toml} - {name: HERDR_SOCKET_PATH, value: /opt/data/herdr/herdr.sock} - - {name: PATH, value: /opt/data/tools/bin:/usr/local/bin:/usr/bin:/bin} + - {name: PATH, value: /opt/data/tools/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin} volumeMounts: - {name: home, mountPath: /opt/data} - {name: tmp, mountPath: /tmp} @@ -416,8 +446,6 @@ spec: if herdr status server >/dev/null 2>&1; then break; fi sleep 1 done - herdr integration install codex || true - herdr integration install claude || true pane_file=/opt/data/herdr/coordinator-pane-id pane="$(cat "${pane_file}" 2>/dev/null || true)" if [ -z "${pane}" ] || ! herdr pane get "${pane}" >/dev/null 2>&1; then @@ -449,7 +477,7 @@ spec: - {name: HERDR_CONFIG_PATH, value: /opt/data/home/.config/herdr/config.toml} - {name: HERDR_SOCKET_PATH, value: /opt/data/herdr/herdr.sock} - {name: PYTHONPATH, value: /opt/hermes} - - {name: PATH, value: /opt/data/tools/bin:/usr/local/bin:/usr/bin:/bin} + - {name: PATH, value: /opt/data/tools/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin} securityContext: allowPrivilegeEscalation: false runAsUser: 10000 diff --git a/testing/tests/test_hermes_herdr.py b/testing/tests/test_hermes_herdr.py index e3dad8f5d..1f906c26b 100644 --- a/testing/tests/test_hermes_herdr.py +++ b/testing/tests/test_hermes_herdr.py @@ -173,3 +173,28 @@ def test_agent_ttyd_defers_identity_to_owner_only_oauth_boundary(): "ports": [{"protocol": "TCP", "port": 7681}], } ] + + +def test_agent_installs_hermes_integration_before_startup(): + deployment = yaml.safe_load((HERMES / "agent-deployment.yaml").read_text()) + pod = deployment["spec"]["template"]["spec"] + init_config = next( + container for container in pod["initContainers"] if container["name"] == "init-config" + ) + assert "ln -s /opt/data /opt/data/home/.hermes" in init_config["command"][-1] + + installer = next( + container + for container in pod["initContainers"] + if container["name"] == "install-herdr-integrations" + ) + command = installer["command"][-1] + assert "herdr integration install codex" in command + assert "herdr integration install claude" in command + assert "herdr integration install hermes" in command + assert "|| true" not in command + + containers = {container["name"]: container for container in pod["containers"]} + for name in ("herdr-tui", "herdr-server"): + env = {item["name"]: item["value"] for item in containers[name]["env"]} + assert "/opt/hermes/.venv/bin" in env["PATH"].split(":")