fix(config): keep anonymous custom endpoints in picker when /v1/models probe fails#2550
Conversation
Adds a reload button to the app titlebar visible only in PWA standalone
or fullscreen mode, and a pull-to-refresh gesture on the messages container
that smooth-scrolls to the top before activating.
The reload button sits next to the message count label and provides a
one-tap refresh for users who installed the WebUI as a home-screen app
where browser navigation controls are unavailable.
The pull-to-refresh gesture detects downward drag at the top of the
message list, shows a visual indicator ('Pull to refresh' / 'Release to refresh'),
and reloads on release past the 80px threshold. When triggered mid-conversation,
it smooth-scrolls to the top first.
…s probe fails When an anonymous custom endpoint (bare base_url, not a named custom_providers[] entry) fails its /v1/models probe, the provider group was silently dropped from the model picker entirely. This made the endpoint unusable even when /v1/chat/completions would work fine. The fix adds an elif branch: if pid == 'custom', a cfg_base_url is configured, but no models were returned by the probe, the group is still added with an empty model list. Users can then select the Custom group and type a model ID manually in the picker's free-form input. Closes nesquena#2542.
Holding for agent review tick + active sweep already shipped #2515 nearbyThanks @espokaos-ops for the anonymous-endpoint picker fallback — this is a real follow-up case to #2515 (custom-provider remote Two notes:
Will revisit on the next sweep tick once agent review completes. |
71c7035
… 0.51.92) (#560) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/nesquena/hermes-webui](https://github.com/nesquena/hermes-webui) | patch | `0.51.90` → `0.51.92` | --- ### Release Notes <details> <summary>nesquena/hermes-webui (ghcr.io/nesquena/hermes-webui)</summary> ### [`v0.51.92`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05192--2026-05-19--Release-BP-stage-385--7-PR-full-sweep-batch--RFC-Slice-3c-clarification--workspace-tree-icon-alignment--project-move-cache-refresh--auto-compression-handoff-metadata--Grok-OAuth-provider-catalog--anonymous-custom-endpoint-picker-fallback--PWA-standalone-reload--pull-to-refresh) [Compare Source](nesquena/hermes-webui@v0.51.91...v0.51.92) ##### Fixed - **PR [#​2563](nesquena/hermes-webui#2563 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2554](nesquena/hermes-webui#2554)) — Align workspace-tree file rows with sibling directory rows by reserving the same expand/collapse toggle slot for files via a new `.file-tree-toggle-placeholder` element. Expanded directories now show child files stepped in at the same icon column as child folders. Directory toggles and file interactions are unchanged; source-level regression coverage and before/after PNGs included. - **PR [#​2561](nesquena/hermes-webui#2561 by [@​nanookclaw](https://github.com/nanookclaw) (closes [#​2551](nesquena/hermes-webui#2551)) — Refresh the authoritative `_allSessions` cache when the project picker moves a session to/from a project. Previous code mutated only the shallow sidebar row copy, so `renderSessionListFromCache()` re-read the unchanged cache and repainted a stale project dot until the next `/api/sessions` poll healed the UI. Both the "Removed from project" and "Moved to <project>" branches now write the new `project_id` into `_allSessions[idx]` before re-rendering. - **PR [#​2567](nesquena/hermes-webui#2567 by [@​dso2ng](https://github.com/dso2ng) (refs [#​2477](nesquena/hermes-webui#2477)) — Surface automatic-compression handoff metadata through the `compressed` SSE event so the active browser stream keeps its completion card even after the backend rotates the session id from the origin to a compressed continuation. The event now carries both `old_session_id` and `new_session_id`/`continuation_session_id`; the frontend `compressed` listener accepts either, and the automatic-compression detail line names the compressed continuation session so the done state isn't silently dropped. - **PR [#​2568](nesquena/hermes-webui#2568 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2545](nesquena/hermes-webui#2545)) — Add the Hermes Agent `xai-oauth` provider to the WebUI's OAuth provider catalog so Grok OAuth accounts authenticated via the Hermes CLI appear in Settings → Providers and the `/api/models` picker. The provider is treated as CLI-managed OAuth (no WebUI API-key form) and uses the live Hermes CLI model catalog when available with a Grok 4.20 static fallback. - **PR [#​2550](nesquena/hermes-webui#2550 by [@​espokaos-ops](https://github.com/espokaos-ops) (refs [#​2542](nesquena/hermes-webui#2542)) — Keep anonymous custom OpenAI-compatible endpoints in the model picker even when the configured `/v1/models` probe fails. Lightweight relays and llama-server-style deployments that authenticate `/v1/chat/completions` but not `/v1/models` no longer have their provider group silently dropped from the picker. Users can type a model id manually in the free-form input when no live catalog is available. ##### Added - **PR [#​2548](nesquena/hermes-webui#2548 by [@​espokaos-ops](https://github.com/espokaos-ops) — Add a PWA-standalone reload affordance. A small refresh button appears in the app titlebar (visible only under `@media (display-mode: standalone), (display-mode: fullscreen)`) so users running the WebUI as an installed home-screen PWA can reload without re-launching the app. Adds a complementary pull-to-refresh gesture on the messages container with an 80px threshold and a smooth-scroll-to-top guard so accidental triggers while reading history feel intentional. 4-viewport screenshots (390/1280/1440/1920, light/dark, hover/idle) included under `docs/pr-media/2548/`. ##### Documentation - **PR [#​2560](nesquena/hermes-webui#2560 by [@​Michaelyklam](https://github.com/Michaelyklam) (refs [#​1925](nesquena/hermes-webui#1925)) — Clarify the RuntimeAdapter Slice 3c state after [#​2544](nesquena/hermes-webui#2544) shipped. The RFC now distinguishes shipped `/api/goal` routing through `RuntimeAdapter.update_goal(...)` from the still-staged `queue_message(...)` protocol method, and explicitly warns not to add a new server-side queue endpoint or queue scheduler merely for adapter symmetry while `/queue` remains browser-side queue/drain behavior. ### [`v0.51.91`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05191--2026-05-18--Release-BO-stage-384--5-PR-full-sweep-batch--reasoning-replay-history-fix--archive-extract-per-session-inbox--fallback-streaming-warnings--sanitized-custom-provider-env-hints--Slice-3c-queuegoal-adapter-routing) [Compare Source](nesquena/hermes-webui@v0.51.90...v0.51.91) ##### Fixed - **PR [#​2536](nesquena/hermes-webui#2536 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2514](nesquena/hermes-webui#2514), refs [#​2535](nesquena/hermes-webui#2535)) — Stop reasoning-only Thinking entries from being replayed into provider-facing history as blank assistant turns. Long WebUI sessions were accumulating duplicated stale Thinking blocks and inflated Activity/tool metadata on later turns when reasoning-only display entries (from interrupted/canceled turns) got reinserted into the restored conversation history. The fix keeps visible Thinking cards in the transcript while filtering them out of provider-facing replay. Settled compact Activity rerenders now also clear previously inserted Thinking rows before rebuilding the visible transcript. - **PR [#​2520](nesquena/hermes-webui#2520 by [@​OneFat3](https://github.com/OneFat3) (refs [#​2247](nesquena/hermes-webui#2247)) — Route archive extraction (`/api/upload/extract`) through the per-session attachment inbox (`_session_attachment_dir`) instead of hardcoded `Path(s.workspace)`, matching the single-file upload path. Extracted archives now land at `<attachment_root>/<session_id>/<archive_stem>/` so session deletion cleanup covers them and per-session isolation is preserved when `HERMES_WEBUI_ATTACHMENT_DIR` is configured. - **PR [#​2505](nesquena/hermes-webui#2505 by [@​cyberdyne187](https://github.com/cyberdyne187) — Surface provider fallback and rate-limit lifecycle notices as auto-clearing fallback warnings in the streaming composer status. The new bridge in `_agent_status_callback` matches agent lifecycle messages containing `rate limited` / `switching to fallback` / `falling back` / `fallback activated` / `trying fallback` and emits them as `warning` events with `type=fallback`, so the existing `static/messages.js` warning channel surfaces them with the correct auto-clear contract instead of letting them drop silently. - **PR [#​2556](nesquena/hermes-webui#2556 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2541](nesquena/hermes-webui#2541)) — Sanitize auto-generated custom-provider API-key environment variable names so endpoint-derived provider ids such as `custom:gpu.local-8000` use POSIX-safe names like `CUSTOM_GPU_LOCAL_8000_API_KEY`. Runtime custom-provider key resolution now checks the sanitized env var first and falls back to the legacy punctuation-preserving name with a one-shot deprecation warning. Configured literal `api_key` values and explicit `key_env` config are unchanged. ##### Documentation - **PR [#​2544](nesquena/hermes-webui#2544 by [@​Michaelyklam](https://github.com/Michaelyklam) (refs [#​1925](nesquena/hermes-webui#1925)) — Implement the first Slice 3c RuntimeAdapter control routing. `RuntimeAdapter` / `LegacyJournalRuntimeAdapter` now expose `queue_message(...)` and `update_goal(...)` as protocol-translator delegates, and the `/api/goal` route uses `update_goal(...)` only when `HERMES_WEBUI_RUNTIME_ADAPTER=legacy-journal` is enabled while preserving the legacy-direct response shape. The change keeps `/queue`'s existing browser-side drain semantics and goal post-turn evaluation in the current agent loop; no runner/sidecar, WebUI-owned queue, goal scheduler, cached-agent table, or execution-survives-restart claim is introduced. </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL3BhdGNoIl19--> Reviewed-on: https://git.erwanleboucher.dev/eleboucher/homelab/pulls/560
…ena#2550/nesquena#2551/nesquena#2554/nesquena#2560/nesquena#2567/nesquena#2568) into process-complete-event PR # Conflicts: # static/sessions.js
…ena#2550/nesquena#2551/nesquena#2554/nesquena#2560/nesquena#2567/nesquena#2568) into process-complete-event PR # Conflicts: # static/sessions.js
When an anonymous custom endpoint (bare base_url, not a named custom_providers[] entry) fails its /v1/models probe, the provider group is silently dropped from the model picker. This makes the endpoint unusable even when the actual /v1/chat/completions endpoint would work fine.
The fix adds an elif branch in get_available_models(): if pid == 'custom', a cfg_base_url is configured, but no models were returned by the probe, the group is still added with an empty model list. Users can then select the Custom group and type a model ID manually in the picker's free-form input.
This covers lightweight local endpoints (llama-server, vLLM, TabbyAPI, etc.) that don't expose a full /v1/models catalog or return an empty response.
Changes
Closes #2542. Refs #2271.