Merge pull request #2293 into stage-359

Skip agent git objects during Docker chown (franksong2702, refs #2237)
This commit is contained in:
Hermes Agent committed 2026-05-15 14:54:59 +00:00
commit 29db680f0a
3 files changed
+47 -1

No files matched your search

+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Fixed
- Docker startup no longer fails when a bind-mounted `~/.hermes/hermes-agent/.git/objects` tree contains read-only git object packs. The root init ownership pass now skips that git object subtree while still chowning the rest of `/home/hermeswebui`, so macOS Docker Desktop bind mounts can start WebUI without requiring writable ownership over agent git internals (fixes #2237).
### Added
- **PR #2099** by @dobby-d-elf — Adds an opt-in `Settings → Preferences → Fade text effect` toggle (off by default). When enabled, newly streamed output tokens are revealed through an adaptive playout buffer and animated with an opacity-only fade similar to ChatGPT and other frontier LLM apps. Implementation details: fade locked per stream to avoid mid-stream toggle rewind; reduced-motion users get non-animated text; live cursor hidden while fade is active; custom renderer on `streaming-markdown` parser wraps only newly-appended words; animated spans replace themselves with plain text on `animationend` (no long-lived wrapper buildup in long responses); unsafe streamed `href`/`src` values blocked in fade renderer `set_attr` path. Performance tuning: 200ms base fade duration scaling to 350ms for fast output, 16ms word stagger, 320ms done-drain wait cap, 160 wps visual cap, max 2-3 words/frame, brief pauses after sentence punctuation. Default-off means existing users see no change. 293-line regression test pinning the contract.
+10 -1
View File
@@ -181,6 +181,15 @@ load_env() {
fi
}
chown_home_hermeswebui() {
# macOS Docker bind mounts can expose hermes-agent git object packs as
# read-only host files. The runtime only needs to read those existing objects;
# requiring chown on them makes startup fail before WebUI can run (#2237).
find /home/hermeswebui \
-path "/home/hermeswebui/.hermes/hermes-agent/.git/objects" -prune \
-o -exec chown -h "${WANTED_UID}:${WANTED_GID}" {} +
}
# The production image does not ship sudo. The entrypoint starts as root only
# long enough to align the hermeswebui UID/GID with mounted volumes, prepare
# root-owned paths, and then drop privileges for the server process.
@@ -209,7 +218,7 @@ if [ "A${whoami}" == "Aroot" ]; then
usermod -o -u "${WANTED_UID}" hermeswebui || error_exit "Failed to set UID of hermeswebui user"
fi
chown -R "${WANTED_UID}:${WANTED_GID}" /home/hermeswebui || error_exit "Failed to set owner of /home/hermeswebui"
chown_home_hermeswebui || error_exit "Failed to set owner of /home/hermeswebui"
echo ""; echo "-- Preparing /app for the hermeswebui runtime user"
mkdir -p /app || error_exit "Failed to create /app directory"
@@ -0,0 +1,33 @@
"""Regression coverage for #2237 Docker startup chown on git object packs."""
from pathlib import Path
import subprocess
REPO = Path(__file__).resolve().parents[1]
INIT_SCRIPT = (REPO / "docker_init.bash").read_text(encoding="utf-8")
def test_home_chown_skips_hermes_agent_git_objects():
assert "chown_home_hermeswebui()" in INIT_SCRIPT
assert "/home/hermeswebui/.hermes/hermes-agent/.git/objects" in INIT_SCRIPT
assert "-prune" in INIT_SCRIPT
assert 'chown -h "${WANTED_UID}:${WANTED_GID}"' in INIT_SCRIPT
def test_root_init_uses_git_object_safe_chown_helper():
root_start = INIT_SCRIPT.index('if [ "A${whoami}" == "Aroot" ]; then')
root_restart = INIT_SCRIPT.index("exec su", root_start)
root_section = INIT_SCRIPT[root_start:root_restart]
assert "chown_home_hermeswebui || error_exit" in root_section
assert 'chown -R "${WANTED_UID}:${WANTED_GID}" /home/hermeswebui' not in root_section
def test_docker_init_bash_syntax_still_valid():
result = subprocess.run(
["bash", "-n", str(REPO / "docker_init.bash")],
capture_output=True,
text=True,
)
assert result.returncode == 0, result.stderr