fix(hermes): put stock TUI in foreground
This commit is contained in:
parent
cb02c5112e
commit
8ae7105ea0
@ -5,10 +5,10 @@ FROM nousresearch/hermes-agent@sha256:9c841866021c54c4596849f6135717e8a4d52ba510
|
||||
USER root
|
||||
|
||||
# Codex uses the distribution bubblewrap package when a bounded sandbox is
|
||||
# requested. Full-access workers rely on the pod as their isolation boundary,
|
||||
# but keep bwrap installed for diagnostics and any future restricted profile.
|
||||
# requested. tmux keeps the stock Hermes TUI alive across browser reconnects;
|
||||
# Herdr remains a background worker transport instead of the visible shell.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends bubblewrap \
|
||||
&& apt-get install -y --no-install-recommends bubblewrap tmux \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Keep a credential-free search provider available for private chat tenants.
|
||||
|
||||
@ -21,10 +21,10 @@ spec:
|
||||
app: hermes-agent
|
||||
annotations:
|
||||
ai.bstein.dev/role: project-coordinator
|
||||
ai.bstein.dev/execution: Hermes delegation with durable Codex and Claude Code CLI workers
|
||||
ai.bstein.dev/execution: Stock Hermes TUI with durable Codex and Claude Code CLI workers
|
||||
ai.bstein.dev/model-policy: Jetson-assisted AUTO routing, low through xhigh, cross-provider fallback
|
||||
ai.bstein.dev/placement: rpi5 preferred; Jetson deferred until state storage is available
|
||||
ai.bstein.dev/config-rev: "20260810-per-subtask-routing"
|
||||
ai.bstein.dev/config-rev: "20260810-stock-tui-per-subtask-routing"
|
||||
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
|
||||
@ -142,7 +142,7 @@ spec:
|
||||
requests: {cpu: 25m, memory: 32Mi}
|
||||
limits: {cpu: 100m, memory: 64Mi}
|
||||
- name: install-agent-tools
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- sh
|
||||
@ -194,7 +194,7 @@ spec:
|
||||
requests: {cpu: 100m, memory: 256Mi}
|
||||
limits: {cpu: "1", memory: 1Gi}
|
||||
- name: patch-auth
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /opt/hermes/.venv/bin/python
|
||||
@ -217,7 +217,7 @@ spec:
|
||||
requests: {cpu: 25m, memory: 64Mi}
|
||||
limits: {cpu: 100m, memory: 128Mi}
|
||||
- name: bootstrap-coordinator
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /opt/hermes/.venv/bin/python
|
||||
@ -243,7 +243,7 @@ spec:
|
||||
requests: {cpu: 50m, memory: 128Mi}
|
||||
limits: {cpu: 500m, memory: 512Mi}
|
||||
- name: install-herdr-integrations
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- sh
|
||||
@ -272,7 +272,7 @@ spec:
|
||||
requests: {cpu: 25m, memory: 32Mi}
|
||||
limits: {cpu: 250m, memory: 128Mi}
|
||||
- name: prepare-ttyd-index
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- /opt/hermes/.venv/bin/python
|
||||
@ -294,7 +294,7 @@ spec:
|
||||
limits: {cpu: 250m, memory: 128Mi}
|
||||
containers:
|
||||
- name: hermes
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: [/opt/hermes/.venv/bin/hermes]
|
||||
args: [gateway, run, --no-supervise]
|
||||
@ -409,7 +409,7 @@ spec:
|
||||
requests: {cpu: 50m, memory: 128Mi}
|
||||
limits: {cpu: 750m, memory: 1Gi}
|
||||
- name: herdr-tui
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: [/bin/sh, -ec]
|
||||
args:
|
||||
@ -426,28 +426,48 @@ spec:
|
||||
--terminal-type xterm-256color \
|
||||
--index /ttyd-index/index.html \
|
||||
--client-option disableReconnect=true \
|
||||
--client-option "titleFixed=Hermes Agent - HERDR" \
|
||||
--client-option "titleFixed=Hermes Agent" \
|
||||
--client-option fontSize=15 \
|
||||
/bin/sh -c '
|
||||
while true; do
|
||||
/opt/data/tools/bin/herdr
|
||||
exit_code=$?
|
||||
printf "\r\nHerdr disconnected (exit %s); reconnecting in 2 seconds...\r\n" "${exit_code}"
|
||||
sleep 2
|
||||
done
|
||||
'
|
||||
/usr/bin/tmux new-session -A \
|
||||
-s hermes-coordinator \
|
||||
-c /opt/data/workspace \
|
||||
/bin/sh -lc '
|
||||
while true; do
|
||||
/opt/hermes/.venv/bin/hermes \
|
||||
--continue \
|
||||
--tui \
|
||||
--yolo \
|
||||
--accept-hooks \
|
||||
--checkpoints
|
||||
exit_code=$?
|
||||
printf "\r\nHermes exited (exit %s); resuming in 2 seconds...\r\n" "${exit_code}"
|
||||
sleep 2
|
||||
done
|
||||
'
|
||||
ports:
|
||||
- {name: herdr-tui, containerPort: 7681, protocol: TCP}
|
||||
env:
|
||||
- {name: HOME, value: /opt/data/home}
|
||||
- {name: HERMES_HOME, value: /opt/data}
|
||||
- {name: HERMES_AUTH_FILE, value: /shared-auth/auth.json}
|
||||
- {name: CODEX_HOME, value: /opt/data/home/.codex}
|
||||
- {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/coordinator:/opt/data/tools/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin}
|
||||
- {name: KUBECONFIG, value: /opt/data/home/.kube/config}
|
||||
- {name: PYTHONPATH, value: /opt/hermes}
|
||||
- {name: PATH, value: /opt/coordinator:/opt/data/tools/bin:/opt/data/home/.local/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin}
|
||||
- {name: PLAYWRIGHT_BROWSERS_PATH, value: /opt/hermes/.playwright}
|
||||
- {name: AGENT_BROWSER_EXECUTABLE_PATH, value: /opt/hermes/.playwright/chromium_headless_shell-1228/chrome-linux/headless_shell}
|
||||
- {name: AGENT_BROWSER_ARGS, value: "--no-sandbox,--disable-dev-shm-usage"}
|
||||
volumeMounts:
|
||||
- {name: home, mountPath: /opt/data}
|
||||
- {name: provider-auth, mountPath: /shared-auth}
|
||||
- {name: coordinator, mountPath: /opt/coordinator, readOnly: true}
|
||||
- {name: auth-patch, mountPath: /opt/hermes/hermes_cli/auth.py, subPath: auth.py}
|
||||
- {name: coordinator, mountPath: /opt/data/home/.local/bin/herdr-dispatch, subPath: herdr_dispatch.py, readOnly: true}
|
||||
- {name: kubeconfig, mountPath: /opt/data/home/.kube/config, subPath: config, readOnly: true}
|
||||
- {name: auto-router-plugin, mountPath: /opt/data/plugins/auto-router, readOnly: true}
|
||||
- {name: tmp, mountPath: /tmp}
|
||||
- {name: ttyd-index, mountPath: /ttyd-index, readOnly: true}
|
||||
startupProbe:
|
||||
@ -478,7 +498,7 @@ spec:
|
||||
requests: {cpu: 25m, memory: 64Mi}
|
||||
limits: {cpu: 500m, memory: 512Mi}
|
||||
- name: herdr-server
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- sh
|
||||
@ -495,60 +515,6 @@ spec:
|
||||
if herdr status server >/dev/null 2>&1; then break; fi
|
||||
sleep 1
|
||||
done
|
||||
pane_file=/opt/data/herdr/coordinator-pane-id
|
||||
pane="$(cat "${pane_file}" 2>/dev/null || true)"
|
||||
pane_live=no
|
||||
if [ -n "${pane}" ]; then
|
||||
for attempt in $(seq 1 20); do
|
||||
if herdr pane process-info --pane "${pane}" >/dev/null 2>&1; then
|
||||
pane_live=yes
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
if [ "${pane_live}" != "yes" ]; then
|
||||
if [ -n "${pane}" ]; then
|
||||
workspace="${pane%%:*}"
|
||||
herdr workspace close "${workspace}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
created="$(herdr workspace create \
|
||||
--cwd /opt/data/workspace \
|
||||
--label coordinator \
|
||||
--env HERMES_HOME=/opt/data \
|
||||
--env HERMES_AUTH_FILE=/shared-auth/auth.json \
|
||||
--env HOME=/opt/data/home \
|
||||
--env KUBECONFIG=/opt/data/home/.kube/config \
|
||||
--env PYTHONPATH=/opt/hermes \
|
||||
--env PLAYWRIGHT_BROWSERS_PATH=/opt/hermes/.playwright \
|
||||
--env AGENT_BROWSER_EXECUTABLE_PATH=/opt/hermes/.playwright/chromium_headless_shell-1228/chrome-linux/headless_shell \
|
||||
--env AGENT_BROWSER_ARGS=--no-sandbox,--disable-dev-shm-usage \
|
||||
--focus)"
|
||||
pane="$(printf '%s' "${created}" | /opt/hermes/.venv/bin/python -c \
|
||||
'import json,sys; print(json.load(sys.stdin)["result"]["root_pane"]["pane_id"])')"
|
||||
printf '%s\n' "${pane}" > "${pane_file}"
|
||||
fi
|
||||
active_workspace="${pane%%:*}"
|
||||
coordinator_workspaces="$(herdr workspace list | /opt/hermes/.venv/bin/python -c \
|
||||
'import json,sys; active=sys.argv[1]; payload=json.load(sys.stdin); print(" ".join(item["workspace_id"] for item in payload["result"]["workspaces"] if item.get("label") == "coordinator" and item["workspace_id"] != active))' \
|
||||
"${active_workspace}")"
|
||||
for stale_workspace in ${coordinator_workspaces}; do
|
||||
herdr workspace close "${stale_workspace}" >/dev/null 2>&1 || true
|
||||
done
|
||||
process_info="$(herdr pane process-info --pane "${pane}" 2>/dev/null || printf '%s\n' '{"result":{"process_info":{"foreground_processes":[]}}}')"
|
||||
coordinator_running="$(printf '%s' "${process_info}" | /opt/hermes/.venv/bin/python -c \
|
||||
'import json,sys; processes=json.load(sys.stdin)["result"]["process_info"].get("foreground_processes", []); print("yes" if any("hermes" in " ".join(str(p.get(k) or "") for k in ("name", "argv0", "cmdline")) for p in processes) else "no")')"
|
||||
if [ "${coordinator_running}" != "yes" ]; then
|
||||
herdr agent start coordinator \
|
||||
--kind hermes \
|
||||
--pane "${pane}" \
|
||||
--timeout 60000
|
||||
fi
|
||||
/opt/hermes/.venv/bin/python /opt/coordinator/herdr_tab_router.py \
|
||||
--workspace-label coordinator \
|
||||
--interval 1 &
|
||||
router_pid=$!
|
||||
trap 'kill "${router_pid}" "${server_pid}" 2>/dev/null || true' TERM INT
|
||||
wait "${server_pid}"
|
||||
env:
|
||||
- {name: HERMES_HOME, value: /opt/data}
|
||||
@ -582,7 +548,7 @@ spec:
|
||||
requests: {cpu: 50m, memory: 128Mi}
|
||||
limits: {cpu: "1", memory: 2Gi}
|
||||
- name: model-steward
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:3f454c13b6050e590598a7e067ef6f2c9b0e7f395219b1d294e59c0020d7b50c
|
||||
image: registry.bstein.dev/bstein/hermes-agent@sha256:46de11122226a68adad6d902e81ef9b4b53deb0433dcc61f57fa43fae2e3a3a5
|
||||
imagePullPolicy: IfNotPresent
|
||||
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/hermes_coordinator.py, --loop, --interval, "3600"]
|
||||
env:
|
||||
|
||||
@ -580,22 +580,19 @@ def test_agent_installs_hermes_integration_before_startup():
|
||||
assert "--no-sandbox" in env["AGENT_BROWSER_ARGS"]
|
||||
|
||||
server_command = containers["herdr-server"]["command"][-1]
|
||||
assert 'herdr pane process-info --pane "${pane}"' in server_command
|
||||
assert 'herdr workspace close "${workspace}"' in server_command
|
||||
assert 'item.get("label") == "coordinator"' in server_command
|
||||
assert 'item["workspace_id"] != active' in server_command
|
||||
assert 'herdr workspace close "${stale_workspace}"' in server_command
|
||||
assert "herdr agent start coordinator" in server_command
|
||||
assert "/opt/coordinator/herdr_tab_router.py" in server_command
|
||||
assert "--workspace-label coordinator" in server_command
|
||||
assert "--kind hermes" in server_command
|
||||
assert "--timeout 60000" in server_command
|
||||
assert "--env AGENT_BROWSER_EXECUTABLE_PATH=" in server_command
|
||||
assert "herdr server" in server_command
|
||||
assert "herdr agent start coordinator" not in server_command
|
||||
assert "/opt/coordinator/herdr_tab_router.py" not in server_command
|
||||
|
||||
tui_command = containers["herdr-tui"]["args"][0]
|
||||
assert "while true" in tui_command
|
||||
assert "Herdr disconnected" in tui_command
|
||||
assert "/opt/data/tools/bin/herdr" in tui_command
|
||||
assert "/usr/bin/tmux new-session -A" in tui_command
|
||||
assert "-s hermes-coordinator" in tui_command
|
||||
assert "/opt/hermes/.venv/bin/hermes" in tui_command
|
||||
assert "--continue" in tui_command
|
||||
assert "--tui" in tui_command
|
||||
assert "--yolo" in tui_command
|
||||
assert "--accept-hooks" in tui_command
|
||||
assert "--checkpoints" in tui_command
|
||||
|
||||
|
||||
def test_agent_mounts_auto_router_into_both_hermes_runtimes():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user