From ee88d8967d6a376f6323590bc27be25d92a49cb3 Mon Sep 17 00:00:00 2001 From: geekypunk Date: Tue, 18 Aug 2026 20:21:43 -0500 Subject: [PATCH] fix(agent): pin hermes-agent and hermes-webui to release tags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both install paths tracked moving branches: agent/Dockerfile defaulted to `main`/`master`, and setup-agent.sh's ensure_clone passed no ref at all, so it took whatever the default branch HEAD happened to be that day. An upstream commit could therefore change what the agent image contains, and break it, with no change on our side — precisely the failure mode the `mcp>=1.0,<2` pin four lines below exists to prevent, left wide open one layer up. Pinned to the current release pair: hermes-agent v2026.8.18 -> e624e9f hermes-webui v0.52.76 -> 3c9304a This is a behaviour change, not a no-op: both branches had already moved past their latest tag (main was 1f234a1, master was 63a562f), so this rolls the runtime back from branch HEAD to the tagged release. Both files are changed together on purpose. Pinning only the Dockerfile would have left host installs on branch HEAD and container installs on a tag, so a bug would reproduce on one path and not the other — the Dockerfile comment already claimed the two tracked each other, and that claim was false. ensure_clone still returns early when a checkout exists, so an install that predates pinning keeps its current ref; silently deleting a user's agent directory to change a version is not this script's call. The message now says so instead of implying the ref was applied. Verified: both tags clone at the expected SHAs with pyproject.toml and requirements.txt present; setup-agent.sh passes bash -n. Co-Authored-By: Claude Opus 5 (1M context) --- agent/Dockerfile | 16 ++++++++++++---- scripts/self-host/setup-agent.sh | 25 +++++++++++++++++++------ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/agent/Dockerfile b/agent/Dockerfile index c86ba45..48006e2 100644 --- a/agent/Dockerfile +++ b/agent/Dockerfile @@ -37,12 +37,20 @@ RUN curl -fsSL https://astral.sh/uv/install.sh | sh \ WORKDIR /opt/deepsql-agent -# Upstream runtime clones. Refs are overridable at build time; defaults track -# what scripts/self-host/setup-agent.sh installs for host-based installs. +# Upstream runtime clones, PINNED to release tags. Overridable at build time; +# defaults track what scripts/self-host/setup-agent.sh installs, so a container +# install and a host install get the identical runtime pair. +# +# These were `main` and `master` — moving branches. That meant an upstream commit +# could change what this image contains, and break it, with no change on our side: +# exactly the failure the `mcp>=1.0,<2` pin below exists to prevent, left open one +# layer up. The webui couples to the agent by direct import, so the two move +# together — bump them as a PAIR and re-validate the agent actually answers, not +# merely that the image builds. ARG AGENT_RUNTIME_REPO=https://github.com/NousResearch/hermes-agent.git -ARG AGENT_RUNTIME_REF=main +ARG AGENT_RUNTIME_REF=v2026.8.18 ARG AGENT_API_REPO=https://github.com/nesquena/hermes-webui.git -ARG AGENT_API_REF=master +ARG AGENT_API_REF=v0.52.76 # Runtime engine (Python agent) RUN git clone --depth 1 --branch "${AGENT_RUNTIME_REF}" "${AGENT_RUNTIME_REPO}" runtime \ diff --git a/scripts/self-host/setup-agent.sh b/scripts/self-host/setup-agent.sh index 3d84f82..3aa8b01 100755 --- a/scripts/self-host/setup-agent.sh +++ b/scripts/self-host/setup-agent.sh @@ -28,6 +28,11 @@ AGENT_DIR="${HERMES_AGENT_DIR:-$HERMES_HOME/hermes-agent}" WEBUI_DIR="${HERMES_WEBUI_DIR:-$HERMES_HOME/hermes-webui}" AGENT_REPO="${HERMES_AGENT_REPO:-https://github.com/NousResearch/hermes-agent.git}" WEBUI_REPO="${HERMES_WEBUI_REPO:-https://github.com/nesquena/hermes-webui.git}" +# Pinned to the same release tags as agent/Dockerfile. A host install and a +# container install must yield the same runtime pair, or a bug reproduces on one +# path and not the other. Bump both files together. +AGENT_REF="${HERMES_AGENT_REF:-v2026.8.18}" +WEBUI_REF="${HERMES_WEBUI_REF:-v0.52.76}" WEBUI_PORT="${HERMES_WEBUI_PORT:-8787}" # Default to loopback so a bare self-host install does not expose the Agent API # on the WAN (nginx /agent-api already gates via auth_request). Override to @@ -57,14 +62,22 @@ resolve_venv_python() { } ensure_clone() { - local dir="$1" repo="$2" label="$3" + local dir="$1" repo="$2" label="$3" ref="$4" if [[ -d "$dir/.git" ]]; then - echo "✓ $label already present at $dir" + # Note: an install that predates pinning keeps whatever ref it already has. + # Re-pinning an existing checkout is deliberately not automatic — deleting a + # user's agent directory to change a version is not this script's call. + echo "✓ $label already present at $dir (ref unchanged; delete the directory to re-pin)" return 0 fi - echo "→ Cloning $label into $dir" + echo "→ Cloning $label at $ref into $dir" mkdir -p "$(dirname "$dir")" - git clone --depth 1 "$repo" "$dir" + if ! git clone --depth 1 --branch "$ref" "$repo" "$dir"; then + echo "Error: could not clone $label at pinned ref '$ref' from $repo." >&2 + echo " If that tag was removed upstream, pick a current one and update" >&2 + echo " BOTH this script and agent/Dockerfile — they must stay in step." >&2 + return 1 + fi } ensure_agent_venv() { @@ -412,8 +425,8 @@ require_command node require_command python3 mkdir -p "$HERMES_HOME" -ensure_clone "$AGENT_DIR" "$AGENT_REPO" "hermes-agent" -ensure_clone "$WEBUI_DIR" "$WEBUI_REPO" "hermes-webui" +ensure_clone "$AGENT_DIR" "$AGENT_REPO" "hermes-agent" "$AGENT_REF" +ensure_clone "$WEBUI_DIR" "$WEBUI_REPO" "hermes-webui" "$WEBUI_REF" ensure_agent_venv ensure_mcp_sdk