From cd9bda57c3b98d68f3d3a0474f59938e3828c2be Mon Sep 17 00:00:00 2001 From: Hermes Date: Wed, 20 May 2026 14:05:51 -0400 Subject: [PATCH] Revert "fix(hermes-workspace): add HOST/ENV vars, drop redundant nodejs install" This reverts commit 735ddcb555769ff2af6e3cc130ec74a0214bcf2c. --- ai/hermes-workspace/Dockerfile | 8 +- ai/hermes-workspace/entrypoint-combined.sh | 173 ++++----------------- 2 files changed, 28 insertions(+), 153 deletions(-) mode change 100755 => 100644 ai/hermes-workspace/entrypoint-combined.sh diff --git a/ai/hermes-workspace/Dockerfile b/ai/hermes-workspace/Dockerfile index 9530f0a..2f40c9a 100644 --- a/ai/hermes-workspace/Dockerfile +++ b/ai/hermes-workspace/Dockerfile @@ -29,12 +29,10 @@ RUN pnpm install --frozen-lockfile && pnpm build # ---------- Stage 2: Hermes Agent + Workspace runtime ---------- FROM nousresearch/hermes-agent:latest -# ---------- Install tmux for Swarm workers + curl for health checks ---------- -# Note: Node.js is already shipped with the base hermets-agent image; apt's nodejs -# would be older. Only add what's missing. +# ---------- Install Node.js + tmux for Workspace + Swarm ---------- USER root RUN apt-get update && apt-get install -y --no-install-recommends \ - tmux curl \ + nodejs tmux ca-certificates curl \ && rm -rf /var/lib/apt/lists/* # ---------- Overlay our forked Hermes source ---------- @@ -117,8 +115,6 @@ USER hermes ENV HERMES_HOME=/opt/data ENV PATH="/opt/data/.local/bin:${PATH}" ENV CHROME_EXECUTABLE=/opt/hermes/.playwright/chromium/chrome-linux/chrome -ENV HOST=0.0.0.0 -ENV NODE_ENV=production RUN chown -R hermes:hermes /opt/hermes/tools /opt/hermes/toolsets.py diff --git a/ai/hermes-workspace/entrypoint-combined.sh b/ai/hermes-workspace/entrypoint-combined.sh old mode 100755 new mode 100644 index b6be66b..614b535 --- a/ai/hermes-workspace/entrypoint-combined.sh +++ b/ai/hermes-workspace/entrypoint-combined.sh @@ -1,154 +1,33 @@ #!/bin/bash -# ── Hermes Workspace Combined Entrypoint ── -# Waits for the Hermes gateway container (hermes:8642) to become healthy, -# then starts the Hermes Workspace web UI in the foreground. -# Supports graceful shutdown via SIGTERM/SIGINT. -# ────────────────────────────────────────── +set -e -set -euo pipefail +# ── Hermes Workspace + Swarm Worker Entrypoint ── +# Starts Hermes Workspace web UI (port 3000) and makes +# hermes CLI + tmux available for Swarm workers. +# The Hermes gateway runs in a separate container (hermes:8642). +# Swarm workers spawned here connect to the gateway via HTTP. +# ────────────────────────────────────────────────────────── -# ── Configuration ────────────────────────────────────────────── -GATEWAY_HOST="${GATEWAY_HOST:-hermes}" -GATEWAY_PORT="${GATEWAY_PORT:-8642}" -GATEWAY_URL="http://${GATEWAY_HOST}:${GATEWAY_PORT}" +# Install custom tools from persistent volume +if [ -f /opt/data/hermes-tools/install.sh ]; then + bash /opt/data/hermes-tools/install.sh || true +fi -HEALTH_ENDPOINT="${HEALTH_ENDPOINT:-/health}" -MAX_RETRIES="${HEALTH_MAX_RETRIES:-60}" -RETRY_INTERVAL="${HEALTH_RETRY_INTERVAL:-2}" - -WORKSPACE_DIR="${WORKSPACE_DIR:-/workspace}" -WORKSPACE_ENTRY="${WORKSPACE_ENTRY:-server-entry.js}" - -PID_FILE="${PID_FILE:-/tmp/workspace.pid}" - -# ── Logging ──────────────────────────────────────────────────── -log_info() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $*"; } -log_warn() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $*"; } -log_error() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $*"; } - -# ── Graceful Shutdown ────────────────────────────────────────── -_workspace_pid="" -_shutting_down=false - -cleanup() { - if [ "$_shutting_down" = true ]; then - return +# Wait for Hermes gateway to be healthy before starting workspace +if [ -n "${HERMES_API_URL:-}" ]; then + echo "Waiting for Hermes gateway..." + for i in $(seq 1 30); do + if curl -fsS "${HERMES_API_URL}/health" >/dev/null 2>&1; then + echo "Gateway healthy after ${i}s" + break fi - _shutting_down=true - - log_info "Shutdown signal received, cleaning up..." - - # Stop workspace process if running - if [ -n "$_workspace_pid" ] && kill -0 "$_workspace_pid" 2>/dev/null; then - log_info "Stopping workspace (PID: $_workspace_pid)..." - kill -TERM "$_workspace_pid" 2>/dev/null || true - - # Give it time to shut down gracefully - local wait_sec=10 - while kill -0 "$_workspace_pid" 2>/dev/null && [ "$wait_sec" -gt 0 ]; do - sleep 1 - wait_sec=$((wait_sec - 1)) - done - - # Force kill if still running - if kill -0 "$_workspace_pid" 2>/dev/null; then - log_warn "Workspace did not shut down gracefully, force killing..." - kill -KILL "$_workspace_pid" 2>/dev/null || true - fi + if [ "$i" -eq 30 ]; then + echo "WARNING: Gateway not healthy after 30s, starting workspace anyway" fi + sleep 1 + done +fi - # Clean up PID file - [ -f "$PID_FILE" ] && rm -f "$PID_FILE" - - log_info "Shutdown complete." - exit 0 -} - -# Trap termination signals for graceful shutdown -trap cleanup SIGTERM SIGINT - -# ── Gateway Health Check ─────────────────────────────────────── -wait_for_gateway() { - local url="${GATEWAY_URL}${HEALTH_ENDPOINT}" - local retries="$MAX_RETRIES" - local interval="$RETRY_INTERVAL" - local attempt=0 - - log_info "Waiting for Hermes gateway at ${GATEWAY_URL}..." - log_info "Max retries: ${retries}, interval: ${interval}s" - - while [ "$attempt" -lt "$retries" ]; do - attempt=$((attempt + 1)) - - if curl -fsS "${url}" >/dev/null 2>&1; then - log_info "Gateway is healthy after ${attempt} attempt(s) (${GATEWAY_URL})" - return 0 - fi - - if [ "$attempt" -lt "$retries" ]; then - log_info "Gateway not ready yet (attempt ${attempt}/${retries}), retrying in ${interval}s..." - sleep "$interval" - fi - done - - log_error "Gateway did not become healthy after ${retries} attempts ($((retries * interval))s)" - return 1 -} - -# ── Workspace Startup ────────────────────────────────────────── -start_workspace() { - local entry="${WORKSPACE_DIR}/${WORKSPACE_ENTRY}" - - if [ ! -d "$WORKSPACE_DIR" ]; then - log_error "Workspace directory not found: ${WORKSPACE_DIR}" - return 1 - fi - - if [ ! -f "$entry" ]; then - log_error "Workspace entry point not found: ${entry}" - return 1 - fi - - log_info "Starting Hermes Workspace web UI..." - log_info " Directory: ${WORKSPACE_DIR}" - log_info " Entry: ${entry}" - - cd "$WORKSPACE_DIR" - - # Start workspace in background so we can trap signals - node --max-old-space-size=2048 "${entry}" & - _workspace_pid=$! - echo "$_workspace_pid" > "$PID_FILE" - - log_info "Workspace started (PID: ${_workspace_pid})" - - # Wait for workspace process - wait "$_workspace_pid" - local exit_code=$? - - log_info "Workspace exited with code ${exit_code}" - return "$exit_code" -} - -# ── Main ─────────────────────────────────────────────────────── -main() { - log_info "=== Hermes Workspace Combined Entrypoint ===" - log_info "Gateway: ${GATEWAY_URL}" - log_info "Workspace: ${WORKSPACE_DIR}/${WORKSPACE_ENTRY}" - log_info "PID file: ${PID_FILE}" - - # Wait for gateway to be healthy - if ! wait_for_gateway; then - log_warn "Proceeding without confirmed gateway health..." - fi - - # Start the workspace - start_workspace - local exit_code=$? - - log_info "Entrypoint exiting with code ${exit_code}" - return "$exit_code" -} - -# Run main; exit with its return code -main "$@" +# Start Hermes Workspace in foreground +cd /workspace +exec node --max-old-space-size=2048 server-entry.js