Release batch B: Docker single-container UID fix + GLM-5.3 catalog (experimental) (#7090)
* feat: add GLM-5.3 to Z.AI model list Add glm-5.3 as the newest zai entry in _PROVIDER_MODELS and a matching zai/glm-5.3 entry in _FALLBACK_MODELS, and bump the Z.AI onboarding default_model from glm-5.1 to glm-5.3 (Z.ai's current flagship; legacy GLM-5.2/5.1 requests are routed to GLM-5.3 per docs.z.ai). Reasoning gating needs no change: _zai_glm_classification() treats GLM >= 5.2 as effort-ladder capable, so glm-5.3 is already covered and pinned by tests/test_zai_reasoning_effort_gating.py. New regression coverage in tests/test_glm_5_3_catalog.py: catalog presence, newest-first ordering, fallback entry, onboarding default, full reasoning_effort ladder, and the get_available_models() payload. * test: restore _cfg_fingerprint in catalog test fixture Review follow-up (#7017): the isolation fixture snapshot restored cfg, _cfg_mtime, and _cfg_path but left _cfg_fingerprint pointing at the temporary config loaded by the payload test. api/config.py uses that fingerprint to distinguish in-memory overrides from changed files (config.py:371), so a stale value could make later same-process tests skip reloading a changed config. Snapshot and restore it like the rest. * fix: keep Z.AI onboarding default at glm-5.1 until direct API serves GLM-5.3 Review follow-up (#7017): GLM-5.3 is live on Z.ai's Coding Plan endpoint only; the direct api.z.ai endpoint the zai provider uses still lists the GLM-5.3 API as coming soon. Defaulting new direct-API users onto glm-5.3 would fail their first message, so the catalog addition stays (opt-in) and the default stays glm-5.1. Bump the default in a follow-up once the direct endpoint serves GLM-5.3. * fix(docker): probe the configured state dir before /workspace for UID/GID (#7027) UID/GID auto-detection probed /workspace before the configured HERMES_WEBUI_STATE_DIR. In a stock single-container image none of the priority-1 candidates exist, but /workspace does — owned by the image's build-time 1024:1024. Detection therefore returned the image's own owner, which carries no information about the host, while the one directory whose owner *is* the host UID by definition — the state-dir bind mount — was never probed. With a host-owned state mount and no explicit WANTED_UID the container remapped to 1024, failed its own state-dir writability check, and restart-looped. The log line made this expensive to debug: 1024 is also the fallback default, so "Auto-detected workspace UID: 1024" read as if detection had found nothing. - probe ${HERMES_WEBUI_STATE_DIR:-/app/data} first, for both UID and GID - keep /workspace as a lower-priority signal (unchanged for setups that actually bind-mount it), and keep the hermes-home probes from #668 - stop treating an explicitly supplied 1024 as "unset": the sentinel and a valid UID were the same number, so an operator who deliberately ran as 1024 got it overwritten by detection. The explicit/detected origin is persisted next to the value because `su` drops the environment when the script re-enters as the runtime user, so the second pass would otherwise see an explicit choice as a detected one. Tests: tests/test_7027_state_dir_uid_probe.py runs the real resolution block under bash with `stat` stubbed, covering the non-1024 state mount, the explicit 1024 override (including across the privilege drop), and the pre-existing /workspace + hermes-home fallback paths. A new state-dir-uid job in the Docker smoke workflow boots a real container on a host-owned state mount and gates on /health. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Release batch B: Docker UID fix + GLM-5.3 catalog (experimental) Two independently gate-passed contributor PRs, rebased fresh onto master and re-gated as a combined stage (Codex SAFE TO SHIP; full suite green except the 8 pre-existing approval-test failures that fail identically on clean origin/master — CI green on the same commit; tracked separately for a fix). - #7027 (@jorgejiro) probe configured state-dir before /workspace for Docker UID/GID; persist explicit marker so a supplied 1024 survives root->su re-entry (fixes the single-container restart loop) (#7034) - #7017 (@rh-id) add GLM-5.3 to the Z.AI model list (onboarding default stays glm-5.1) Co-authored-by: jorgejiro <jorgejiro@users.noreply.github.com> Co-authored-by: rh-id <rh-id@users.noreply.github.com> --------- Co-authored-by: Ruby Hartono <58564005+rh-id@users.noreply.github.com> Co-authored-by: Jorge <jorgejiro@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: n <a@n> Co-authored-by: jorgejiro <jorgejiro@users.noreply.github.com> Co-authored-by: rh-id <rh-id@users.noreply.github.com>
This commit is contained in:
7 files changed
+880
-16
No files matched your search
@@ -468,6 +468,44 @@ services:
|
||||
|
||||
Then configure the URL as `http://host.docker.internal:<port>`. Also ensure the host service binds to an address reachable from containers (not only a loopback interface the Docker bridge cannot reach) and that your host firewall allows the connection.
|
||||
|
||||
### 9. "Failed to verify state directory" / restart loop on a bind-mounted state dir (#7027)
|
||||
|
||||
**Symptom**: Single-container deploy with the state directory bind-mounted from a
|
||||
host directory, no `WANTED_UID` set. The container exits 1 and restart-loops:
|
||||
|
||||
```
|
||||
-- Auto-detected workspace UID: 1024 (from /workspace)
|
||||
touch: cannot touch '/app/data/.testfile': Permission denied
|
||||
!! ERROR: Failed to verify state directory at /app/data
|
||||
```
|
||||
|
||||
**Cause**: UID auto-detection used to read `/workspace` before the configured
|
||||
state directory. In a stock image `/workspace` exists and is owned by the
|
||||
image's own build-time `1024:1024`, so detection returned a value that carries
|
||||
no information about the host — and because `1024` is also the fallback default,
|
||||
the log read as if detection had found nothing.
|
||||
|
||||
**Fix**: Fixed in the init script — the configured `HERMES_WEBUI_STATE_DIR` is
|
||||
now probed first. The full order is:
|
||||
|
||||
1. `$HERMES_WEBUI_STATE_DIR` (default `/app/data`) — a bind mount by definition
|
||||
in a single-container deploy, so its owner is the host identity to match
|
||||
2. `/home/hermeswebui/.hermes`, `$HERMES_HOME`, `/opt/data` — the hermes-home
|
||||
shared volume in two-container setups (#668)
|
||||
3. `/workspace` — used only when nothing above resolves
|
||||
4. `1024` — fallback default
|
||||
|
||||
Root-owned candidates (UID 0, e.g. a freshly created named volume) are skipped
|
||||
at every step. An explicitly supplied `WANTED_UID`/`WANTED_GID` always wins and
|
||||
is never overwritten by detection — including the value `1024`, which earlier
|
||||
versions treated as "unset".
|
||||
|
||||
If you are on an older image, the workaround is to set the IDs explicitly:
|
||||
|
||||
```bash
|
||||
docker run -e WANTED_UID=$(id -u) -e WANTED_GID=$(id -g) ...
|
||||
```
|
||||
|
||||
## Multi-container architecture
|
||||
|
||||
The two- and three-container setups use **named Docker volumes** (not bind mounts) by default for a reason: named volumes solve the UID/GID problem by construction. Docker creates the volume's root directory with the correct ownership, all containers reading/writing to it see the same files, no host-side permission setup required.
|
||||
@@ -588,6 +626,7 @@ volumes:
|
||||
- #681 — tools running in WebUI container, not agent container (architectural)
|
||||
- #668 — auto-detect UID/GID from mounted volume
|
||||
- #569 — UID/GID detection priority order
|
||||
- #7027 — state dir probed before `/workspace` in UID/GID detection (see [#9 above](#9-failed-to-verify-state-directory--restart-loop-on-a-bind-mounted-state-dir-7027))
|
||||
|
||||
If you hit a new failure mode not covered here, please [open an issue](https://github.com/nesquena/hermes-webui/issues/new) with:
|
||||
|
||||
|
||||
Reference in new issue
Block a user