hermes(agent): retry dashboard ticket acquisition
All checks were successful
Tests / Declarative: Post Actions passed: 231

This commit is contained in:
jenkins 2026-08-10 23:57:32 -03:00
parent 0bec6edba3
commit 987c6e4cee
3 changed files with 71 additions and 12 deletions

View File

@ -27,7 +27,13 @@ const socketBefore = [
' const ws = new WebSocket(url);',
].join("\n");
const socketAfter = [
' const url = await api.buildWsUrl("/api/pty", params);',
' let url: string;',
' try {',
' url = await api.buildWsUrl("/api/pty", params);',
' } catch {',
' if (!unmounting) scheduleReconnect(1006);',
' return;',
' }',
' if (unmounting) return;',
' const ws = new WebSocket(url);',
].join("\n");
@ -70,6 +76,32 @@ const socketStateAfter = [
' let ws: WebSocket | null = null;',
' let reconnectTimer: ReturnType<typeof setTimeout> | null = null;',
].join("\n");
const ticketBefore = [
' const url = await buildWsUrl("/api/events", { channel });',
' if (unmounting) {',
' return;',
' }',
' ws = new WebSocket(url);',
].join("\n");
const ticketAfter = [
' let url: string;',
' try {',
' url = await buildWsUrl("/api/events", { channel });',
' } catch {',
' if (unmounting) return;',
' const attempt = Math.min(eventsRetryAttempt.current + 1, 6);',
' eventsRetryAttempt.current = attempt;',
' const delay = Math.min(500 * 2 ** (attempt - 1), 5000);',
' setError("events feed disconnected — tool calls may not appear; reconnecting…");',
' reconnectTimer = setTimeout(() => {',
' reconnectTimer = null;',
' if (!unmounting) setVersion((v) => v + 1);',
' }, delay);',
' return;',
' }',
' if (unmounting) return;',
' ws = new WebSocket(url);',
].join("\n");
const handlersBefore = [
' ws.addEventListener("error", () => surface(DISCONNECTED));',
'',
@ -121,6 +153,7 @@ const cleanupAfter = [
for (const [before, after, label] of [
[retryStateBefore, retryStateAfter, "retry state"],
[socketStateBefore, socketStateAfter, "socket state"],
[ticketBefore, ticketAfter, "ticket retry"],
[handlersBefore, handlersAfter, "socket handlers"],
[cleanupBefore, cleanupAfter, "socket cleanup"],
]) {

View File

@ -170,7 +170,7 @@ spec:
requests: {cpu: 25m, memory: 32Mi}
limits: {cpu: 100m, memory: 64Mi}
- name: install-agent-tools
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command:
- sh
@ -218,7 +218,7 @@ spec:
requests: {cpu: 100m, memory: 256Mi}
limits: {cpu: "1", memory: 1Gi}
- name: patch-auth
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command:
- /opt/hermes/.venv/bin/python
@ -241,7 +241,7 @@ spec:
requests: {cpu: 25m, memory: 64Mi}
limits: {cpu: 100m, memory: 128Mi}
- name: patch-tui-gateway
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command:
- /opt/hermes/.venv/bin/python
@ -264,7 +264,7 @@ spec:
requests: {cpu: 25m, memory: 64Mi}
limits: {cpu: 100m, memory: 128Mi}
- name: patch-codex-runtime
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command:
- /opt/hermes/.venv/bin/python
@ -295,7 +295,7 @@ spec:
requests: {cpu: 25m, memory: 64Mi}
limits: {cpu: 100m, memory: 128Mi}
- name: bootstrap-coordinator
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command:
- /opt/hermes/.venv/bin/python
@ -305,7 +305,10 @@ spec:
- {name: HERMES_HOME, value: /opt/data}
- {name: HERMES_AUTH_FILE, value: /shared-auth/auth.json}
- {name: HOME, value: /opt/data/home}
- {name: CODEX_HOME, value: /opt/data/home/.codex}
- {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude}
- {name: PYTHONPATH, value: /opt/hermes}
- {name: PATH, value: /opt/coordinator:/opt/data/tools/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin}
securityContext:
allowPrivilegeEscalation: false
runAsUser: 10000
@ -321,7 +324,7 @@ spec:
requests: {cpu: 50m, memory: 128Mi}
limits: {cpu: 500m, memory: 512Mi}
- name: configure-agent-clients
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command:
- sh
@ -359,7 +362,7 @@ spec:
requests: {cpu: 25m, memory: 32Mi}
limits: {cpu: 250m, memory: 128Mi}
- name: prepare-ttyd-index
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command:
- /opt/hermes/.venv/bin/python
@ -381,7 +384,7 @@ spec:
limits: {cpu: 250m, memory: 128Mi}
containers:
- name: hermes
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command: [/init, /opt/hermes/docker/main-wrapper.sh]
args: [gateway, run]
@ -512,7 +515,7 @@ spec:
- {name: allowlist, mountPath: /etc/oauth2-proxy, readOnly: true}
- {name: oauth-tmp, mountPath: /tmp}
- name: terminal
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command: [/bin/sh, -ec]
args:
@ -604,7 +607,7 @@ spec:
requests: {cpu: 25m, memory: 64Mi}
limits: {cpu: 500m, memory: 512Mi}
- name: cli-lane-runner
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command: [/bin/sh, -ec]
args:
@ -645,14 +648,17 @@ spec:
requests: {cpu: 100m, memory: 256Mi}
limits: {cpu: "3", memory: 6Gi}
- name: model-steward
image: registry.bstein.dev/bstein/hermes-agent@sha256:0577eb22d28b1ffc649405d31919b2527d9e591ccaa4a1e168dd6d6392a5a43f
image: registry.bstein.dev/bstein/hermes-agent@sha256:cf07be056feea8e4f2d5512899f990732f3d26b4915257de8f90105d96cec67d
imagePullPolicy: IfNotPresent
command: [/opt/hermes/.venv/bin/python, /opt/coordinator/hermes_coordinator.py, --loop, --interval, "3600"]
env:
- {name: HERMES_HOME, value: /opt/data}
- {name: HERMES_AUTH_FILE, value: /shared-auth/auth.json}
- {name: HOME, value: /opt/data/home}
- {name: CODEX_HOME, value: /opt/data/home/.codex}
- {name: CLAUDE_CONFIG_DIR, value: /opt/data/home/.claude}
- {name: PYTHONPATH, value: /opt/hermes}
- {name: PATH, value: /opt/coordinator:/opt/data/tools/bin:/opt/hermes/.venv/bin:/usr/local/bin:/usr/bin:/bin}
securityContext:
allowPrivilegeEscalation: false
runAsUser: 10000

View File

@ -723,6 +723,8 @@ def test_agent_dashboard_reconnects_all_transient_websockets():
assert "eventsRetryAttempt.current" in dockerfile
assert "if (!unmounting) setVersion((v) => v + 1);" in dockerfile
assert "events feed rejected (${ev.code}) — reload the page" in dockerfile
assert 'url = await api.buildWsUrl("/api/pty", params);' in dockerfile
assert 'url = await buildWsUrl("/api/events", { channel });' in dockerfile
def test_agent_refreshes_routes_after_restoring_cli_logins():
@ -740,6 +742,24 @@ def test_agent_refreshes_routes_after_restoring_cli_logins():
env = {item["name"]: item["value"] for item in configure["env"]}
assert env["HERMES_AUTH_FILE"] == "/shared-auth/auth.json"
assert env["PYTHONPATH"] == "/opt/hermes"
for name in ("bootstrap-coordinator", "configure-agent-clients"):
route_env = {
item["name"]: item["value"]
for item in init_containers[name]["env"]
}
assert route_env["CODEX_HOME"] == "/opt/data/home/.codex"
assert "/opt/data/tools/bin" in route_env["PATH"]
containers = {
item["name"]: item
for item in deployment["spec"]["template"]["spec"]["containers"]
}
steward_env = {
item["name"]: item["value"]
for item in containers["model-steward"]["env"]
}
assert steward_env["CODEX_HOME"] == "/opt/data/home/.codex"
assert "/opt/data/tools/bin" in steward_env["PATH"]
def test_flux_health_checks_follow_the_owner_oauth_sidecar():