lrmd/hermes
0
1# HuggingMes - Hermes Agent Gateway for Hugging Face Spaces2 3ARG HERMES_AGENT_VERSION=latest4FROM nousresearch/hermes-agent:${HERMES_AGENT_VERSION}5 6USER root7 8RUN apt-get update && apt-get install -y --no-install-recommends \9 ca-certificates \10 curl \11 jq \12 sudo \13 python3 \14 python3-venv \15 python3-pip \16 chromium \17 dbus \18 dbus-x11 \19 libnss3 \20 libatk1.0-0 \21 libatk-bridge2.0-0 \22 libdrm2 \23 libgbm1 \24 libxcomposite1 \25 libxdamage1 \26 libxrandr2 \27 libxkbcommon0 \28 libx11-6 \29 libxext6 \30 libxfixes3 \31 fonts-dejavu-core \32 fonts-liberation \33 fonts-noto-color-emoji \34 && (apt-get install -y --no-install-recommends libasound2 2>/dev/null \35 || apt-get install -y --no-install-recommends libasound2t64 2>/dev/null \36 || true) \37 && rm -rf /var/lib/apt/lists/* \38 && uv pip install --python /opt/hermes/.venv/bin/python --no-cache-dir \39 huggingface_hub \40 hf_transfer \41 "jupyterlab>=4.0,<5" \42 "tornado>=6.4" \43 "ipywidgets>=8.1" \44 && printf 'hermes ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/hermes \45 && chmod 0440 /etc/sudoers.d/hermes \46 && /usr/sbin/visudo -cf /etc/sudoers.d/hermes47 48COPY --chown=hermes:hermes start.sh /opt/huggingmes/start.sh49COPY --chown=hermes:hermes health-server.js /opt/huggingmes/health-server.js50COPY --chown=hermes:hermes hermes-sync.py /opt/huggingmes/hermes-sync.py51COPY --chown=hermes:hermes cloudflare-proxy-setup.py /opt/huggingmes/cloudflare-proxy-setup.py52COPY --chown=hermes:hermes cloudflare-keepalive-setup.py /opt/huggingmes/cloudflare-keepalive-setup.py53COPY --chown=hermes:hermes env-builder.html /opt/huggingmes/env-builder.html54COPY --chown=hermes:hermes env-builder.js /opt/huggingmes/env-builder.js55 56RUN chmod +x \57 /opt/huggingmes/start.sh \58 /opt/huggingmes/hermes-sync.py \59 /opt/huggingmes/cloudflare-proxy-setup.py \60 /opt/huggingmes/cloudflare-keepalive-setup.py61 62# Patch kanban migration: wrap ALTER TABLE ADD COLUMN in try/except so a63# persisted DB with the column already present doesn't crash the gateway.64# Entire block wrapped in try/except — skips silently if Hermes fixes this65# upstream or the file structure changes.66RUN python3 - <<'PY'67import sys68try:69 from pathlib import Path70 71 p = Path("/opt/hermes/hermes_cli/kanban_db.py")72 if not p.exists():73 print("kanban patch: file not found, skipping")74 sys.exit(0)75 76 src = p.read_text(encoding="utf-8", errors="replace")77 sentinel = "# huggingmes: idempotent-alter"78 if sentinel in src:79 print("kanban patch: already applied, skipping")80 sys.exit(0)81 82 old = (83 ' conn.execute(\n'84 ' "ALTER TABLE tasks ADD COLUMN consecutive_failures "\n'85 ' "INTEGER NOT NULL DEFAULT 0"\n'86 ' )'87 )88 new = (89 f' try: {sentinel}\n'90 ' conn.execute(\n'91 ' "ALTER TABLE tasks ADD COLUMN consecutive_failures "\n'92 ' "INTEGER NOT NULL DEFAULT 0"\n'93 ' )\n'94 ' except Exception:\n'95 ' pass'96 )97 98 if old not in src:99 print("kanban patch: pattern not found, may be fixed upstream, skipping")100 sys.exit(0)101 102 p.write_text(src.replace(old, new), encoding="utf-8")103 print("kanban patch: applied")104except Exception as e:105 print(f"kanban patch: error ({e}), skipping", file=sys.stderr)106PY107 108# Ensure hermes CLI is discoverable in ALL shell types (login, interactive,109# non-interactive). /etc/profile.d/ is sourced by login shells after /etc/profile110# resets PATH, so this survives even full environment resets.111RUN echo 'export PATH="/opt/hermes/.venv/bin:/opt/data/.local/bin:$PATH"' \112 > /etc/profile.d/hermes-venv.sh113 114ENV HERMES_HOME=/opt/data \115 HUGGINGMES_APP_DIR=/opt/huggingmes \116 HERMES_AGENT_VERSION=${HERMES_AGENT_VERSION} \117 PYTHONUNBUFFERED=1 \118 PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium119 120EXPOSE 7861121 122HEALTHCHECK --interval=30s --timeout=5s --start-period=60s \123 CMD curl -fsS http://localhost:7861/health || exit 1124 125CMD ["/opt/huggingmes/start.sh"]126 