From bc88e37647d83de80229ac410a824cfec848ecca Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Mon, 27 Jul 2026 21:30:35 -0700 Subject: [PATCH] fix(hermes): update Hermes Agent to 0.18.2 Signed-off-by: Antonio Martinez --- agents/hermes/Dockerfile | 8 ++++---- agents/hermes/Dockerfile.base | 10 +++++----- agents/hermes/hermes-wrapper.py | 6 +++--- agents/hermes/manifest.yaml | 6 +++--- agents/hermes/patch-langfuse-credentials.mts | 2 +- agents/hermes/patch-session-list-preview.py | 4 ++-- src/lib/domain/sandbox/connect-env.test.ts | 1 + src/lib/domain/sandbox/connect-env.ts | 1 + test/hermes-doctor-config-hash.test.ts | 2 +- test/update-hermes-agent-script.test.ts | 8 ++++---- 10 files changed, 25 insertions(+), 23 deletions(-) diff --git a/agents/hermes/Dockerfile b/agents/hermes/Dockerfile index 175e54201be..230b5cf701d 100644 --- a/agents/hermes/Dockerfile +++ b/agents/hermes/Dockerfile @@ -245,7 +245,7 @@ RUN chmod 755 /usr/local/bin/nemoclaw-start /usr/local/lib/nemoclaw/sandbox-init RUN test -x /usr/local/lib/nemoclaw/validate-hermes-env-secret-boundary.py \ || { echo "ERROR: validate-hermes-env-secret-boundary.py missing or not executable" >&2; exit 1; } -# Hermes v0.18.0 computes `sessions list` preview from the first user message, +# Hermes v0.18.2 computes `sessions list` preview from the first user message, # while #5254's user-facing expectation is that the existing row reflects the # latest resumed/continued one-shot turn. Patch only the pinned query shape and # prove the SessionDB list contract at build time so a Hermes update cannot @@ -266,7 +266,7 @@ assert rows and rows[0]["id"] == session_id, rows assert rows[0]["preview"] == "NEMOCLAW_PREVIEW_LATEST", rows PY -# Hermes v0.18.0's bundled Langfuse plugin rejects OpenShell resolver +# Hermes v0.18.2's bundled Langfuse plugin rejects OpenShell resolver # placeholders before the SDK can construct its Basic-auth headers. Accept only # the exact public/secret placeholder bound to the matching standard Langfuse # key; raw keys keep Hermes' upstream pk-lf-/sk-lf- validation. The patcher @@ -354,10 +354,10 @@ RUN hermes_version_output="$(/usr/local/bin/hermes --version)" \ echo "ERROR: could not parse Hermes semver from: $hermes_version_output" >&2; \ exit 1; \ fi \ - && if [ "$hermes_semver" != "0.18.0" ] \ + && if [ "$hermes_semver" != "0.18.2" ] \ && { grep -q '_translate_resumed_oneshot' /usr/local/lib/nemoclaw/hermes-wrapper.py \ || grep -q 'EXPECTED_OCCURRENCES' /usr/local/lib/nemoclaw/patch-hermes-session-list-preview.py; }; then \ - echo "ERROR: installed Hermes ${hermes_semver} but Hermes v0.18.0 compatibility workarounds are still installed; re-review #5254 workaround removal before upgrading Hermes" >&2; \ + echo "ERROR: installed Hermes ${hermes_semver} but Hermes v0.18.2 compatibility workarounds are still installed; re-review #5254 workaround removal before upgrading Hermes" >&2; \ exit 1; \ fi # This runs before `/usr/local/bin/hermes` is moved to `hermes.real`, so the diff --git a/agents/hermes/Dockerfile.base b/agents/hermes/Dockerfile.base index 40d5a083115..cbf36898f6d 100644 --- a/agents/hermes/Dockerfile.base +++ b/agents/hermes/Dockerfile.base @@ -29,11 +29,11 @@ ENV DEBIAN_FRONTEND=noninteractive # pyproject.toml, HERMES_TARBALL_SHA256 the GitHub tarball checksum, and # HERMES_NPM_INTEGRITY the `npm view hermes-agent@ dist.integrity` # sha512 used as a registry cross-check at build time. -# Calver tag v2026.7.1 = Hermes Agent v0.18.0. -ARG HERMES_VERSION=v2026.7.1 -ARG HERMES_SEMVER=0.18.0 -ARG HERMES_TARBALL_SHA256=ec8a380629cc2f3f2102dd92cad50c4ded706fe59c0e359a05681166a0ae2991 -ARG HERMES_NPM_INTEGRITY=sha512-fS+8MsE69shNPmFnKDrE1a+KUDEEXgbyN/QM7J+2nh294gTjh2wCknk2tfMsD03GhSxl7YwyDmp6e5HLYzw8yA== +# Calver tag v2026.7.7.2 = Hermes Agent v0.18.2. +ARG HERMES_VERSION=v2026.7.7.2 +ARG HERMES_SEMVER=0.18.2 +ARG HERMES_TARBALL_SHA256=f5d1022eed3763a768cf7b0f0844831f0170a35f54eb8d18223f2e93f503025e +ARG HERMES_NPM_INTEGRITY=sha512-Zhkhl209frEHGh65S3+eGZu/M+mFPFQwQeBOnG/MtRfAFEfRMkji+deyjH7TFrQNcp+RHioiBamCFYDNR6dPlw== ARG HERMES_UV_EXTRAS="anthropic messaging web pty mcp" ARG UV_VERSION=0.11.8 diff --git a/agents/hermes/hermes-wrapper.py b/agents/hermes/hermes-wrapper.py index 05b1e01572c..45ae99a33ae 100755 --- a/agents/hermes/hermes-wrapper.py +++ b/agents/hermes/hermes-wrapper.py @@ -289,9 +289,9 @@ def _run_gateway_guard(guard_path: str) -> int: "--resume": "--resume", } # Keep this allowlist aligned with the top-level flags accepted by the pinned -# Hermes Agent CLI in agents/hermes/Dockerfile.base (HERMES_VERSION=v2026.7.1, -# HERMES_SEMVER=0.18.0) and agents/hermes/manifest.yaml (expected_version -# "0.18.0"). Unknown flags deliberately fail closed by passing the original argv +# Hermes Agent CLI in agents/hermes/Dockerfile.base (HERMES_VERSION=v2026.7.7.2, +# HERMES_SEMVER=0.18.2) and agents/hermes/manifest.yaml (expected_version +# "0.18.2"). Unknown flags deliberately fail closed by passing the original argv # through to upstream Hermes. _BOOLEAN_FLAGS = { "--worktree", diff --git a/agents/hermes/manifest.yaml b/agents/hermes/manifest.yaml index 4003b773c76..a8c789625aa 100644 --- a/agents/hermes/manifest.yaml +++ b/agents/hermes/manifest.yaml @@ -16,9 +16,9 @@ homepage: "https://github.com/NousResearch/hermes-agent" install_method: curl # curl install.sh | bash binary_path: /usr/local/bin/hermes version_command: "hermes --version" -expected_version: "0.18.0" -# Hermes reports semver from `hermes --version` (e.g. `0.18.0`) even though its -# GitHub release cadence is calendar-based (`v2026.7.1`). Declaring the +expected_version: "0.18.2" +# Hermes reports semver from `hermes --version` (e.g. `0.18.2`) even though its +# GitHub release cadence is calendar-based (`v2026.7.7.2`). Declaring the # scheme keeps the staleness check off the shape heuristic when a manifest # could otherwise straddle both schemes (#6049). version_scheme: semver diff --git a/agents/hermes/patch-langfuse-credentials.mts b/agents/hermes/patch-langfuse-credentials.mts index e0daf9e23c3..3cf6234819e 100644 --- a/agents/hermes/patch-langfuse-credentials.mts +++ b/agents/hermes/patch-langfuse-credentials.mts @@ -7,7 +7,7 @@ import process from "node:process"; import { pathToFileURL } from "node:url"; /** - * Patch the Langfuse validator bundled with pinned Hermes v2026.7.1 / 0.18.0. + * Patch the Langfuse validator bundled with pinned Hermes v2026.7.7.2 / 0.18.2. * * Hermes rejects OpenShell resolver placeholders before the Langfuse SDK can * turn them into outbound authentication headers. NemoClaw keeps the real diff --git a/agents/hermes/patch-session-list-preview.py b/agents/hermes/patch-session-list-preview.py index be26b35763b..46f9f6df33b 100755 --- a/agents/hermes/patch-session-list-preview.py +++ b/agents/hermes/patch-session-list-preview.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -"""Patch pinned Hermes v0.18.0 session-list previews to show the latest user turn. +"""Patch pinned Hermes v0.18.2 session-list previews to show the latest user turn. Source-of-truth note for this localized Hermes runtime patch: - - Invalid state: Hermes v0.18.0 computes `sessions list` preview text from + - Invalid state: Hermes v0.18.2 computes `sessions list` preview text from the first user message, but #5254's resumed/continued one-shot UX expects the original row to reflect the latest appended turn. - Value being patched: pinned/prebuilt `/opt/hermes/hermes_state.py` diff --git a/src/lib/domain/sandbox/connect-env.test.ts b/src/lib/domain/sandbox/connect-env.test.ts index 21402eef891..aaedcb193d8 100644 --- a/src/lib/domain/sandbox/connect-env.test.ts +++ b/src/lib/domain/sandbox/connect-env.test.ts @@ -21,6 +21,7 @@ describe("sandbox connect environment helpers", () => { expect(NEMOCLAW_HERMES_LIGHT_SKIN_REVIEWED_HERMES_VERSIONS).toEqual([ "v2026.6.19", "v2026.7.1", + "v2026.7.7.2", ]); }); diff --git a/src/lib/domain/sandbox/connect-env.ts b/src/lib/domain/sandbox/connect-env.ts index c4e5e4dc172..21117284f75 100644 --- a/src/lib/domain/sandbox/connect-env.ts +++ b/src/lib/domain/sandbox/connect-env.ts @@ -7,6 +7,7 @@ export const NEMOCLAW_HERMES_LIGHT_SKIN_NAME = "nemoclaw-light"; export const NEMOCLAW_HERMES_LIGHT_SKIN_REVIEWED_HERMES_VERSIONS = [ "v2026.6.19", "v2026.7.1", + "v2026.7.7.2", ] as const; // Compatibility boundary: remove this NemoClaw-managed light skin once the diff --git a/test/hermes-doctor-config-hash.test.ts b/test/hermes-doctor-config-hash.test.ts index 11e678ae132..b31f153295a 100644 --- a/test/hermes-doctor-config-hash.test.ts +++ b/test/hermes-doctor-config-hash.test.ts @@ -52,7 +52,7 @@ describe("Hermes doctor and config hash boundary", () => { expect(result.status).toBe(1); expect(result.stderr).toContain( - "Hermes v0.18.0 compatibility workarounds are still installed", + "Hermes v0.18.2 compatibility workarounds are still installed", ); } finally { fs.rmSync(tmp, { recursive: true, force: true }); diff --git a/test/update-hermes-agent-script.test.ts b/test/update-hermes-agent-script.test.ts index 9a0de687eda..466c6763615 100644 --- a/test/update-hermes-agent-script.test.ts +++ b/test/update-hermes-agent-script.test.ts @@ -16,7 +16,7 @@ const HERMES_BASE_DOCKERFILE = path.join( "Dockerfile.base", ); const HERMES_MANIFEST = path.join(import.meta.dirname, "..", "agents", "hermes", "manifest.yaml"); -const TARGET_TAG = "v2026.7.1"; +const TARGET_TAG = "v2026.7.7.2"; const CURRENT_INSTALLED_BASE = [ "# Calver tag v2026.6.5 = Hermes Agent v0.16.0.", @@ -88,7 +88,7 @@ printf 'fake archive' > "$output" ); writeExecutable( path.join(fakeBin, "tar"), - "#!/usr/bin/env bash\nprintf 'version = \"0.18.0\"\\n'\n", + "#!/usr/bin/env bash\nprintf 'version = \"0.18.2\"\\n'\n", ); writeExecutable(path.join(fakeBin, "npm"), "#!/usr/bin/env bash\nprintf 'sha512-test\\n'\n"); writeExecutable( @@ -107,7 +107,7 @@ esac set -euo pipefail printf '%s|%s\\n' "\${NEMOCLAW_HERMES_SANDBOX_BASE_IMAGE_REF:-}" "$*" >> "$FAKE_NEMOHERMES_LOG" if [[ "$*" == "hermes exec -- hermes --version" ]]; then - printf '0.18.0\\n' + printf '0.18.2\\n' fi `, ); @@ -130,7 +130,7 @@ fi expect(run.status, `${run.stdout}\n${run.stderr}`).toBe(0); expect(fs.readFileSync(dockerLog, "utf8")).toContain(`tag ${baseRef} ${pinnedRef}`); expect(fs.readFileSync(nemohermesLog, "utf8")).toContain(`${pinnedRef}|hermes rebuild`); - expect(run.stdout).toContain("OK: sandbox reports Hermes Agent v0.18.0"); + expect(run.stdout).toContain("OK: sandbox reports Hermes Agent v0.18.2"); } finally { fs.rmSync(tmp, { recursive: true, force: true }); }