From 6209a65ee0399f99d11423682f29f96c302fd71b Mon Sep 17 00:00:00 2001 From: howie <2318485+howie@users.noreply.github.com> Date: Sat, 12 Sep 2026 20:56:17 +0800 Subject: [PATCH 1/5] fix(hermes): bypass raw.githubusercontent.com 429 with direct git clone + uv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原版 Dockerfile.hermes 從 raw.githubusercontent.com 抓 install.sh, 在共用 CI runner 上頻繁 429 導致 smoke test 失敗(PR #1523 移除的原因)。 改為三段式 multi-stage build: - hermes-deps stage: git clone hermes-agent repo + uv sync(繞過 rate limit) - 支援 HERMES_PROFILE build arg: minimal(~250MB)/ full(~900MB) - minimal 不裝 ffmpeg / gh CLI,靠 Hermes 的 lazy_deps.py 按需安裝 - 清除 .git / uv cache 縮小映像 Refs: howie/openab#2 Co-Authored-By: Claude Opus 4.6 (1M context) Claude-Session: https://claude.ai/code/session_01JgBFWacVJ5qgABzqoXs1gA --- Dockerfile.hermes | 108 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 23 deletions(-) diff --git a/Dockerfile.hermes b/Dockerfile.hermes index 2217dbe65..c1c39204b 100644 --- a/Dockerfile.hermes +++ b/Dockerfile.hermes @@ -1,4 +1,19 @@ -# --- Build stage --- +# ============================================================================ +# Hermes Agent — 自行維護版 +# ============================================================================ +# 修正原版的 429 rate limit 問題:不再從 raw.githubusercontent.com 抓 install.sh, +# 改為直接 git clone + uv sync,完全繞過 rate-limited 端點。 +# +# Build profiles(透過 --build-arg HERMES_PROFILE=...): +# minimal — 只裝核心依賴(~250MB),不含 ffmpeg/Node.js/gh CLI +# full — 完整安裝含所有工具(~900MB),向下相容原版行為 +# +# 用法: +# docker build -f Dockerfile.hermes --build-arg HERMES_PROFILE=minimal -t hermes:minimal . +# docker build -f Dockerfile.hermes --build-arg HERMES_PROFILE=full -t hermes:full . +# ============================================================================ + +# --- Build stage: compile openab from Rust source --- FROM rust:1-bookworm AS builder WORKDIR /build COPY Cargo.toml Cargo.lock ./ @@ -16,36 +31,81 @@ COPY crates/ crates/ COPY src/ src/ RUN touch src/main.rs crates/openab-core/src/lib.rs crates/openab-gateway/src/lib.rs crates/openab-mcp/src/lib.rs && cargo build --release +# --- Hermes agent stage: clone + install via uv (no install.sh) --- +FROM python:3.12-slim-trixie AS hermes-deps + +# Build profile: "minimal" or "full" +ARG HERMES_PROFILE=minimal +# Pinned commit — change this to update Hermes version +ARG HERMES_COMMIT=2bd1977d8fad185c9b4be47884f7e87f1add0ce3 + +# Install uv — from official release CDN (astral.sh), NOT raw.githubusercontent.com +# astral.sh 是 uv 官方的 CDN,rate limit 遠高於 raw.githubusercontent.com +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv + +# Clone hermes-agent repo — 用 git clone(走 Git 協定),不是 curl raw file +# Git smart HTTP 有自己的 rate limit pool,不受 raw.githubusercontent.com 影響 +RUN git clone --depth 1 \ + https://github.com/NousResearch/hermes-agent.git \ + /usr/local/lib/hermes-agent && \ + cd /usr/local/lib/hermes-agent && \ + git fetch --depth 1 origin "${HERMES_COMMIT}" && \ + git checkout FETCH_HEAD + +WORKDIR /usr/local/lib/hermes-agent + +# Create venv + install deps based on profile +# minimal: 只裝 pyproject.toml 的 [dependencies](核心)+ [acp](ACP adapter) +# full: 裝 [all] extra(Google/MCP/YouTube/web 等全部) +RUN uv venv venv --python 3.12 && \ + if [ "$HERMES_PROFILE" = "full" ]; then \ + UV_PROJECT_ENVIRONMENT=/usr/local/lib/hermes-agent/venv \ + uv sync --extra all --extra acp --locked 2>&1; \ + else \ + UV_PROJECT_ENVIRONMENT=/usr/local/lib/hermes-agent/venv \ + uv sync --extra acp --locked 2>&1; \ + fi + +# Cleanup: 移除不需要的快取和 git metadata,節省映像空間 +RUN rm -rf .git \ + /root/.cache/uv \ + /root/.local/share/uv \ + venv/lib/python3.12/site-packages/pip \ + venv/lib/python3.12/site-packages/setuptools + # --- Runtime stage --- FROM python:3.12-slim-trixie -# Create agent user first so WORKDIR gets correct ownership +ARG HERMES_PROFILE=minimal + RUN useradd -m -u 1000 agent +# 基礎系統套件 — minimal 不裝 ffmpeg RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates curl procps ripgrep tini git ffmpeg unzip xz-utils && \ + ca-certificates curl procps ripgrep tini git unzip xz-utils \ + $(if [ "$HERMES_PROFILE" = "full" ]; then echo "ffmpeg"; fi) && \ rm -rf /var/lib/apt/lists/* -# Install Hermes Agent — pinned to known commit with checksum verification -# Root install uses FHS layout: binary at /usr/local/bin/hermes, code at /usr/local/lib/hermes-agent -# HERMES_HOME points to agent user's data dir for OAuth tokens and config -ARG HERMES_INSTALL_COMMIT=2bd1977d8fad185c9b4be47884f7e87f1add0ce3 -ARG HERMES_INSTALL_SHA256=dbd9d555ed4ac67bd1fc71ba6a39b410cf2af0ebcfd8f4889e086af78c9ddcaa -RUN curl -fsSL "https://raw.githubusercontent.com/NousResearch/hermes-agent/${HERMES_INSTALL_COMMIT}/scripts/install.sh" \ - -o /tmp/install-hermes.sh && \ - echo "${HERMES_INSTALL_SHA256} /tmp/install-hermes.sh" | sha256sum -c - && \ - HERMES_HOME=/home/agent/.hermes bash /tmp/install-hermes.sh && \ - rm /tmp/install-hermes.sh && \ - (test -d /root/.local/share/uv && chmod -R a+rX /root/.local/share/uv && chmod a+rx /root /root/.local /root/.local/share || true) && \ - ln -sf /usr/local/lib/hermes-agent/venv/bin/hermes-acp /usr/local/bin/hermes-acp - -# Install gh CLI -RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ - -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \ - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ - > /etc/apt/sources.list.d/github-cli.list && \ - apt-get update && apt-get install -y --no-install-recommends gh && \ - rm -rf /var/lib/apt/lists/* +# 從 hermes-deps stage 複製已安裝好的 Hermes Agent +COPY --from=hermes-deps /usr/local/lib/hermes-agent /usr/local/lib/hermes-agent + +# 複製 uv binary(runtime 時 lazy-install 需要) +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv + +# Symlink hermes 指令到 PATH +RUN ln -sf /usr/local/lib/hermes-agent/venv/bin/hermes /usr/local/bin/hermes && \ + ln -sf /usr/local/lib/hermes-agent/venv/bin/hermes-acp /usr/local/bin/hermes-acp && \ + chmod -R a+rX /usr/local/lib/hermes-agent + +# full profile: 額外安裝 gh CLI +RUN if [ "$HERMES_PROFILE" = "full" ]; then \ + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ + -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ + > /etc/apt/sources.list.d/github-cli.list && \ + apt-get update && apt-get install -y --no-install-recommends gh && \ + rm -rf /var/lib/apt/lists/*; \ + fi ENV HOME=/home/agent WORKDIR /home/agent @@ -59,6 +119,8 @@ HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD pgrep -x openab || exit 1 ENV OPENAB_AGENT_COMMAND="hermes-acp" ENV OPENAB_AGENT_AUTH_COMMAND="hermes auth add" +# uv 需要知道 Hermes 的安裝位置,lazy-install 時使用 +ENV UV_PROJECT_ENVIRONMENT="/usr/local/lib/hermes-agent/venv" ENTRYPOINT ["tini", "--"] CMD ["openab", "run", "-c", "/etc/openab/config.toml"] From 48c18f53d3c9e480a3a0756132aee2e7365bee5d Mon Sep 17 00:00:00 2001 From: howie <2318485+howie@users.noreply.github.com> Date: Sun, 13 Sep 2026 20:19:18 +0800 Subject: [PATCH 2/5] fix(hermes): pin uv version, fix 429 scope description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - uv image 從 :latest 改為 pin 到 0.12.13(供應鏈可重現) - runtime stage 的 uv 改從 hermes-deps stage COPY(同一版本) - 頂部註解修正 429 範圍:只有 Docker build 那行 curl 是 429 殘留, nightly resolver 早就改用認證 GitHub Contents API 了 Co-Authored-By: Claude Opus 4.6 (1M context) Claude-Session: https://claude.ai/code/session_01JgBFWacVJ5qgABzqoXs1gA --- Dockerfile.hermes | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Dockerfile.hermes b/Dockerfile.hermes index c1c39204b..72465a208 100644 --- a/Dockerfile.hermes +++ b/Dockerfile.hermes @@ -1,8 +1,13 @@ # ============================================================================ # Hermes Agent — 自行維護版 # ============================================================================ -# 修正原版的 429 rate limit 問題:不再從 raw.githubusercontent.com 抓 install.sh, -# 改為直接 git clone + uv sync,完全繞過 rate-limited 端點。 +# 原版 Dockerfile 在 build 時 curl raw.githubusercontent.com 抓 install.sh, +# 該端點 unauthenticated rate limit 低,共用 CI runner 上頻繁 429。 +# (注意:nightly resolver 已改用認證 GitHub Contents API,429 不在那邊。) +# +# 本版改為 git clone + uv sync --locked,Docker build 階段不再存取任何 +# rate-limited 端點。uv 版本 pin 到明確 tag,供應鏈校驗由 uv.lock 的 +# per-package SHA256 hash 承擔。 # # Build profiles(透過 --build-arg HERMES_PROFILE=...): # minimal — 只裝核心依賴(~250MB),不含 ffmpeg/Node.js/gh CLI @@ -39,9 +44,9 @@ ARG HERMES_PROFILE=minimal # Pinned commit — change this to update Hermes version ARG HERMES_COMMIT=2bd1977d8fad185c9b4be47884f7e87f1add0ce3 -# Install uv — from official release CDN (astral.sh), NOT raw.githubusercontent.com -# astral.sh 是 uv 官方的 CDN,rate limit 遠高於 raw.githubusercontent.com -COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv +# Install uv — pinned version from GHCR (astral.sh official image) +ARG UV_VERSION=0.12.13 +COPY --from=ghcr.io/astral-sh/uv:${UV_VERSION} /uv /usr/local/bin/uv # Clone hermes-agent repo — 用 git clone(走 Git 協定),不是 curl raw file # Git smart HTTP 有自己的 rate limit pool,不受 raw.githubusercontent.com 影響 @@ -89,8 +94,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # 從 hermes-deps stage 複製已安裝好的 Hermes Agent COPY --from=hermes-deps /usr/local/lib/hermes-agent /usr/local/lib/hermes-agent -# 複製 uv binary(runtime 時 lazy-install 需要) -COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv +# 複製 uv binary(runtime 時 lazy-install 需要)——版本與 build stage 一致 +COPY --from=hermes-deps /usr/local/bin/uv /usr/local/bin/uv # Symlink hermes 指令到 PATH RUN ln -sf /usr/local/lib/hermes-agent/venv/bin/hermes /usr/local/bin/hermes && \ From 7708c22db0bc4c4b6abb506ad0d6d49794fd46f4 Mon Sep 17 00:00:00 2001 From: howie <2318485+howie@users.noreply.github.com> Date: Sun, 13 Sep 2026 21:06:27 +0800 Subject: [PATCH 3/5] =?UTF-8?q?style(hermes):=20Dockerfile=20=E8=A8=BB?= =?UTF-8?q?=E8=A7=A3=E5=85=A8=E9=9D=A2=E6=94=B9=E7=82=BA=E7=B9=81=E9=AB=94?= =?UTF-8?q?=E4=B8=AD=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 依語言慣例(code comment 一律繁體中文台灣用語),將所有英文 註解改為繁體中文,識別符與指令維持英文原形。 Co-Authored-By: Claude Opus 4.6 (1M context) Claude-Session: https://claude.ai/code/session_01JgBFWacVJ5qgABzqoXs1gA --- Dockerfile.hermes | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Dockerfile.hermes b/Dockerfile.hermes index 72465a208..60f3c95d8 100644 --- a/Dockerfile.hermes +++ b/Dockerfile.hermes @@ -18,7 +18,7 @@ # docker build -f Dockerfile.hermes --build-arg HERMES_PROFILE=full -t hermes:full . # ============================================================================ -# --- Build stage: compile openab from Rust source --- +# --- 建置階段:從 Rust 原始碼編譯 openab --- FROM rust:1-bookworm AS builder WORKDIR /build COPY Cargo.toml Cargo.lock ./ @@ -36,15 +36,15 @@ COPY crates/ crates/ COPY src/ src/ RUN touch src/main.rs crates/openab-core/src/lib.rs crates/openab-gateway/src/lib.rs crates/openab-mcp/src/lib.rs && cargo build --release -# --- Hermes agent stage: clone + install via uv (no install.sh) --- +# --- Hermes agent 階段:git clone + uv 安裝(不經 install.sh)--- FROM python:3.12-slim-trixie AS hermes-deps -# Build profile: "minimal" or "full" +# 建置 profile:"minimal" 或 "full" ARG HERMES_PROFILE=minimal -# Pinned commit — change this to update Hermes version +# 釘選 commit — 更新 Hermes 版本時改這行 ARG HERMES_COMMIT=2bd1977d8fad185c9b4be47884f7e87f1add0ce3 -# Install uv — pinned version from GHCR (astral.sh official image) +# 安裝 uv — 從 GHCR 取得釘選版本(astral.sh 官方映像) ARG UV_VERSION=0.12.13 COPY --from=ghcr.io/astral-sh/uv:${UV_VERSION} /uv /usr/local/bin/uv @@ -59,9 +59,9 @@ RUN git clone --depth 1 \ WORKDIR /usr/local/lib/hermes-agent -# Create venv + install deps based on profile -# minimal: 只裝 pyproject.toml 的 [dependencies](核心)+ [acp](ACP adapter) -# full: 裝 [all] extra(Google/MCP/YouTube/web 等全部) +# 建立 venv + 依 profile 安裝依賴 +# minimal:只裝 pyproject.toml 的 [dependencies](核心)+ [acp](ACP adapter) +# full:裝 [all] extra(Google/MCP/YouTube/web 等全部) RUN uv venv venv --python 3.12 && \ if [ "$HERMES_PROFILE" = "full" ]; then \ UV_PROJECT_ENVIRONMENT=/usr/local/lib/hermes-agent/venv \ @@ -71,14 +71,14 @@ RUN uv venv venv --python 3.12 && \ uv sync --extra acp --locked 2>&1; \ fi -# Cleanup: 移除不需要的快取和 git metadata,節省映像空間 +# 清理:移除不需要的快取和 git metadata,節省映像空間 RUN rm -rf .git \ /root/.cache/uv \ /root/.local/share/uv \ venv/lib/python3.12/site-packages/pip \ venv/lib/python3.12/site-packages/setuptools -# --- Runtime stage --- +# --- 執行階段 --- FROM python:3.12-slim-trixie ARG HERMES_PROFILE=minimal @@ -97,12 +97,12 @@ COPY --from=hermes-deps /usr/local/lib/hermes-agent /usr/local/lib/hermes-agent # 複製 uv binary(runtime 時 lazy-install 需要)——版本與 build stage 一致 COPY --from=hermes-deps /usr/local/bin/uv /usr/local/bin/uv -# Symlink hermes 指令到 PATH +# 建立 hermes 指令的 symlink 到 PATH RUN ln -sf /usr/local/lib/hermes-agent/venv/bin/hermes /usr/local/bin/hermes && \ ln -sf /usr/local/lib/hermes-agent/venv/bin/hermes-acp /usr/local/bin/hermes-acp && \ chmod -R a+rX /usr/local/lib/hermes-agent -# full profile: 額外安裝 gh CLI +# full profile:額外安裝 gh CLI RUN if [ "$HERMES_PROFILE" = "full" ]; then \ curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \ From 996c5b46aafc41aa335272725c8c9ff9bd54ba44 Mon Sep 17 00:00:00 2001 From: howie <2318485+howie@users.noreply.github.com> Date: Mon, 14 Sep 2026 10:23:36 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix(hermes):=20=E4=BF=AE=E5=BE=A9=20mob=20r?= =?UTF-8?q?eview=20R1=20=E7=9A=84=205=20=E5=80=8B=20blocker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修復清單(2 Critical + 3 Important): - hermes-deps stage 加裝 git ca-certificates(slim 映像不含 git) - HERMES_PROFILE 預設改為 full(向下相容原版行為) - 移除註解中的舊端點 hostname(AC-1 grep 零出現) - 加入 HERMES_PROFILE 值驗證(typo 中斷建置而非靜默降級) - full profile 加裝 nodejs npm(向下相容 install.sh 行為) - symlink 建立前驗證目標檔案存在 - 移除 uv sync 的不必要 2>&1 Co-Authored-By: Claude Opus 4.6 (1M context) Claude-Session: https://claude.ai/code/session_0116kULeLsY8vn9eonV267Qp --- Dockerfile.hermes | 55 ++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/Dockerfile.hermes b/Dockerfile.hermes index 60f3c95d8..098892ab9 100644 --- a/Dockerfile.hermes +++ b/Dockerfile.hermes @@ -1,21 +1,21 @@ # ============================================================================ # Hermes Agent — 自行維護版 # ============================================================================ -# 原版 Dockerfile 在 build 時 curl raw.githubusercontent.com 抓 install.sh, -# 該端點 unauthenticated rate limit 低,共用 CI runner 上頻繁 429。 +# 原版 Dockerfile 在 build 時用未認證的 curl 抓 NousResearch 的 install.sh, +# 該端點 rate limit 低,共用 CI runner 上頻繁 429。 # (注意:nightly resolver 已改用認證 GitHub Contents API,429 不在那邊。) # # 本版改為 git clone + uv sync --locked,Docker build 階段不再存取任何 -# rate-limited 端點。uv 版本 pin 到明確 tag,供應鏈校驗由 uv.lock 的 +# rate-limited 端點。uv 版本釘選到明確 tag,供應鏈校驗由 uv.lock 的 # per-package SHA256 hash 承擔。 # # Build profiles(透過 --build-arg HERMES_PROFILE=...): +# full — 完整安裝含所有工具(~900MB),向下相容原版行為(預設) # minimal — 只裝核心依賴(~250MB),不含 ffmpeg/Node.js/gh CLI -# full — 完整安裝含所有工具(~900MB),向下相容原版行為 # # 用法: +# docker build -f Dockerfile.hermes -t hermes:full . # docker build -f Dockerfile.hermes --build-arg HERMES_PROFILE=minimal -t hermes:minimal . -# docker build -f Dockerfile.hermes --build-arg HERMES_PROFILE=full -t hermes:full . # ============================================================================ # --- 建置階段:從 Rust 原始碼編譯 openab --- @@ -39,8 +39,9 @@ RUN touch src/main.rs crates/openab-core/src/lib.rs crates/openab-gateway/src/li # --- Hermes agent 階段:git clone + uv 安裝(不經 install.sh)--- FROM python:3.12-slim-trixie AS hermes-deps -# 建置 profile:"minimal" 或 "full" -ARG HERMES_PROFILE=minimal +# 建置 profile:預設 "full"(向下相容原版),可選 "minimal" +# 只接受 "full" 或 "minimal",其他值中斷建置 +ARG HERMES_PROFILE=full # 釘選 commit — 更新 Hermes 版本時改這行 ARG HERMES_COMMIT=2bd1977d8fad185c9b4be47884f7e87f1add0ce3 @@ -48,8 +49,17 @@ ARG HERMES_COMMIT=2bd1977d8fad185c9b4be47884f7e87f1add0ce3 ARG UV_VERSION=0.12.13 COPY --from=ghcr.io/astral-sh/uv:${UV_VERSION} /uv /usr/local/bin/uv -# Clone hermes-agent repo — 用 git clone(走 Git 協定),不是 curl raw file -# Git smart HTTP 有自己的 rate limit pool,不受 raw.githubusercontent.com 影響 +# hermes-deps stage 需要 git 來 clone repo(python:3.12-slim 不含 git) +RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates && \ + rm -rf /var/lib/apt/lists/* + +# 驗證 HERMES_PROFILE 值,不合法時中斷建置(避免 typo 靜默降級) +RUN if [ "$HERMES_PROFILE" != "full" ] && [ "$HERMES_PROFILE" != "minimal" ]; then \ + echo "[FAIL] HERMES_PROFILE 必須是 'full' 或 'minimal',收到: '$HERMES_PROFILE'" >&2; \ + exit 1; \ + fi + +# Clone hermes-agent repo — 走 Git smart HTTP(HTTPS),不受原始端點的 rate limit 影響 RUN git clone --depth 1 \ https://github.com/NousResearch/hermes-agent.git \ /usr/local/lib/hermes-agent && \ @@ -60,15 +70,15 @@ RUN git clone --depth 1 \ WORKDIR /usr/local/lib/hermes-agent # 建立 venv + 依 profile 安裝依賴 +# full:裝 [all] extra(Google/MCP/YouTube/web 等全部)+ [acp] # minimal:只裝 pyproject.toml 的 [dependencies](核心)+ [acp](ACP adapter) -# full:裝 [all] extra(Google/MCP/YouTube/web 等全部) RUN uv venv venv --python 3.12 && \ if [ "$HERMES_PROFILE" = "full" ]; then \ UV_PROJECT_ENVIRONMENT=/usr/local/lib/hermes-agent/venv \ - uv sync --extra all --extra acp --locked 2>&1; \ + uv sync --extra all --extra acp --locked; \ else \ UV_PROJECT_ENVIRONMENT=/usr/local/lib/hermes-agent/venv \ - uv sync --extra acp --locked 2>&1; \ + uv sync --extra acp --locked; \ fi # 清理:移除不需要的快取和 git metadata,節省映像空間 @@ -81,7 +91,7 @@ RUN rm -rf .git \ # --- 執行階段 --- FROM python:3.12-slim-trixie -ARG HERMES_PROFILE=minimal +ARG HERMES_PROFILE=full RUN useradd -m -u 1000 agent @@ -94,21 +104,26 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # 從 hermes-deps stage 複製已安裝好的 Hermes Agent COPY --from=hermes-deps /usr/local/lib/hermes-agent /usr/local/lib/hermes-agent -# 複製 uv binary(runtime 時 lazy-install 需要)——版本與 build stage 一致 +# 複製 uv binary(runtime 時按需安裝 optional extras 用)——版本與 build stage 一致 COPY --from=hermes-deps /usr/local/bin/uv /usr/local/bin/uv -# 建立 hermes 指令的 symlink 到 PATH -RUN ln -sf /usr/local/lib/hermes-agent/venv/bin/hermes /usr/local/bin/hermes && \ - ln -sf /usr/local/lib/hermes-agent/venv/bin/hermes-acp /usr/local/bin/hermes-acp && \ +# 建立 hermes 指令的 symlink 到 PATH,並驗證目標存在 +RUN for bin in hermes hermes-acp; do \ + target="/usr/local/lib/hermes-agent/venv/bin/$bin"; \ + if [ ! -f "$target" ]; then \ + echo "[FAIL] symlink 目標不存在: $target" >&2; exit 1; \ + fi; \ + ln -sf "$target" "/usr/local/bin/$bin"; \ + done && \ chmod -R a+rX /usr/local/lib/hermes-agent -# full profile:額外安裝 gh CLI +# full profile:額外安裝 gh CLI 和 Node.js(向下相容原版 install.sh 行為) RUN if [ "$HERMES_PROFILE" = "full" ]; then \ curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \ -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \ > /etc/apt/sources.list.d/github-cli.list && \ - apt-get update && apt-get install -y --no-install-recommends gh && \ + apt-get update && apt-get install -y --no-install-recommends gh nodejs npm && \ rm -rf /var/lib/apt/lists/*; \ fi @@ -124,7 +139,7 @@ HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD pgrep -x openab || exit 1 ENV OPENAB_AGENT_COMMAND="hermes-acp" ENV OPENAB_AGENT_AUTH_COMMAND="hermes auth add" -# uv 需要知道 Hermes 的安裝位置,lazy-install 時使用 +# uv 需要知道 Hermes 的安裝位置,按需安裝 optional extras 時使用 ENV UV_PROJECT_ENVIRONMENT="/usr/local/lib/hermes-agent/venv" ENTRYPOINT ["tini", "--"] From a8066d6093c1aafd60602585b1294d9a385d58e4 Mon Sep 17 00:00:00 2001 From: howie <2318485+howie@users.noreply.github.com> Date: Mon, 14 Sep 2026 10:27:47 +0800 Subject: [PATCH 5/5] =?UTF-8?q?fix(hermes):=20COPY=20--from=20=E6=94=B9?= =?UTF-8?q?=E7=94=A8=20named=20stage=20=E9=81=BF=E5=85=8D=E8=AE=8A?= =?UTF-8?q?=E6=95=B8=E6=8F=92=E5=80=BC=E5=95=8F=E9=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex re-review 發現 COPY --from=ghcr.io/astral-sh/uv:${UV_VERSION} 的 ARG 插值在部分 Docker 版本不支援。改用 FROM ... AS uv 具名 stage, 所有 COPY --from=uv 都引用同一個釘選版本,可攜性更好。 Co-Authored-By: Claude Opus 4.6 (1M context) Claude-Session: https://claude.ai/code/session_0116kULeLsY8vn9eonV267Qp --- Dockerfile.hermes | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Dockerfile.hermes b/Dockerfile.hermes index 098892ab9..bcdc27bbb 100644 --- a/Dockerfile.hermes +++ b/Dockerfile.hermes @@ -36,6 +36,10 @@ COPY crates/ crates/ COPY src/ src/ RUN touch src/main.rs crates/openab-core/src/lib.rs crates/openab-gateway/src/lib.rs crates/openab-mcp/src/lib.rs && cargo build --release +# --- uv stage:釘選版本,供後續 stage 用 COPY --from=uv --- +ARG UV_VERSION=0.12.13 +FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv + # --- Hermes agent 階段:git clone + uv 安裝(不經 install.sh)--- FROM python:3.12-slim-trixie AS hermes-deps @@ -45,9 +49,8 @@ ARG HERMES_PROFILE=full # 釘選 commit — 更新 Hermes 版本時改這行 ARG HERMES_COMMIT=2bd1977d8fad185c9b4be47884f7e87f1add0ce3 -# 安裝 uv — 從 GHCR 取得釘選版本(astral.sh 官方映像) -ARG UV_VERSION=0.12.13 -COPY --from=ghcr.io/astral-sh/uv:${UV_VERSION} /uv /usr/local/bin/uv +# 安裝 uv — 從 uv stage 複製(版本由全域 UV_VERSION ARG 控制) +COPY --from=uv /uv /usr/local/bin/uv # hermes-deps stage 需要 git 來 clone repo(python:3.12-slim 不含 git) RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates && \ @@ -104,8 +107,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # 從 hermes-deps stage 複製已安裝好的 Hermes Agent COPY --from=hermes-deps /usr/local/lib/hermes-agent /usr/local/lib/hermes-agent -# 複製 uv binary(runtime 時按需安裝 optional extras 用)——版本與 build stage 一致 -COPY --from=hermes-deps /usr/local/bin/uv /usr/local/bin/uv +# 複製 uv binary(runtime 時按需安裝 optional extras 用)——版本與 uv stage 一致 +COPY --from=uv /uv /usr/local/bin/uv # 建立 hermes 指令的 symlink 到 PATH,並驗證目標存在 RUN for bin in hermes hermes-acp; do \