Seed bundled skills for WebUI profile creation - #2315
1 commit merged into
Conversation
SummaryReading the diff against Code reference
profile_path.mkdir(parents=True, exist_ok=True)
# Seed bundled skills for non-cloned profiles (#2305).
# Cloned profiles should preserve the clone-source behaviour and must not
# receive a second bundled-skill overlay.
if clone_from is None:
try:
from hermes_cli.profiles import seed_profile_skills
seed_profile_skills(profile_path, quiet=True)
except ImportError:
logger.debug(...)
except Exception:
logger.warning(..., exc_info=True)
_write_endpoint_to_config(profile_path, base_url=base_url, api_key=api_key)I verified The placement after TestsThe 5-test suite at
The fixture pattern in One minor: VerdictLGTM. Code change matches maintainer's preferred direction from #2305 exactly. Tests are thorough, isolated, and avoid the module-reload footgun. CHANGELOG entry present at Comparison with parallel PR #2314 (filed ~30 minutes earlier by @WanderWang): the production code is functionally equivalent, but this PR's test isolation is materially cleaner — no |
7ac4bf4
Seed bundled skills for WebUI profile creation (Michaelyklam, closes nesquena#2305) # Conflicts: # CHANGELOG.md
… 0.51.74) (#501) This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ghcr.io/nesquena/hermes-webui](https://github.com/nesquena/hermes-webui) | patch | `0.51.67` → `0.51.74` | --- ### Release Notes <details> <summary>nesquena/hermes-webui (ghcr.io/nesquena/hermes-webui)</summary> ### [`v0.51.74`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05174--2026-05-16--Release-AX-stage-367--4-PR-safe-lane-batch--2362-table-cell-spacing--2363-run-state-consistency-RFC--2365-customproviders-list-format--2367-settings-sidebar-i18n) [Compare Source](nesquena/hermes-webui@v0.51.73...v0.51.74) ##### Added - **PR [#​2363](nesquena/hermes-webui#2363 by [@​franksong2702](https://github.com/franksong2702) (refs [#​2361](nesquena/hermes-webui#2361), refs [#​1925](nesquena/hermes-webui#1925)) — Adds `docs/rfcs/webui-run-state-consistency-contract.md` as a documentation companion to the [#​1925](nesquena/hermes-webui#1925) runtime-boundary RFC. Documents the shared coherence contract across visible transcript, model context, pending turn metadata, live stream, run journal, compression handoff, browser timeline cache, and sidebar metadata. Complementary to [#​1925](nesquena/hermes-webui#1925): that RFC says where execution ownership should move, this one says what must stay coherent across the current and future state layers. ##### Fixed - **PR [#​2362](nesquena/hermes-webui#2362 by [@​franksong2702](https://github.com/franksong2702) (fixes [#​2360](nesquena/hermes-webui#2360)) — Markdown table rows no longer become too tall when cell text is wrapped in paragraph tags by the renderer. Adds a table-specific CSS reset for `.msg-body td p` and `.msg-body th p` so the global `margin-bottom: 10px` rule on `.msg-body p` doesn't add unwanted vertical space inside table cells. Especially visible on narrow viewports such as iPad Safari/Chrome. - **PR [#​2365](nesquena/hermes-webui#2365 by [@​mccxj](https://github.com/mccxj) (fixes [#​1106](nesquena/hermes-webui#1106)) — `get_available_models()` now handles YAML-list format `custom_providers.models` entries in addition to dict format. Pre-fix, declaring models as a list (`[m1, m2]`) or list-of-dicts (`[{id: m1, label: ...}]`) in `config.yaml` silently discarded every model from that provider in the picker dropdown because the code only recognized dict shape (`{model_id: {}}`). Now supports all three YAML shapes consistently with existing provider-config and live-models-fallback handlers. - **PR [#​2367](nesquena/hermes-webui#2367 by [@​mccxj](https://github.com/mccxj) — Settings sidebar menu items (Conversation, Appearance, Preferences, Plugins, System) now respect locale selection. Pre-fix these were hardcoded English; only Providers had `data-i18n`. Adds `data-i18n` attributes plus the missing `settings_tab_plugins` key. **Stage-367 maintainer fix applied inline**: the PR only added the new key to English, breaking 5 locale-parity tests. Added `settings_tab_plugins` translations to all 10 non-English locales (it/ja/ru/es/de/zh/zh-TW/pt/ko/fr). ### [`v0.51.73`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05173--2026-05-16--Release-AW-stage-366--1-PR-safe-lane-batch--2357-compression-reference-card-anchoring-fix) [Compare Source](nesquena/hermes-webui@v0.51.72...v0.51.73) ##### Fixed - **PR [#​2357](nesquena/hermes-webui#2357 by [@​franksong2702](https://github.com/franksong2702) (fixes [#​2355](nesquena/hermes-webui#2355)) — Auto-compression reference cards no longer get mixed into the final answer turn after a session rotation. Pre-fix, `_insertCompressionLikeNodeByRawIdx()` appended the compression-reference node to the future assistant anchor turn's blocks, which projected the `[CONTEXT COMPACTION — REFERENCE ONLY]` card into the live tail. The fix inserts the node *before* the anchor segment so the reference card stays a sibling, not a child of the answer turn. ### [`v0.51.72`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05172--2026-05-16--Release-AV-stage-365--2-PR-safe-lane-batch--2354-recovered-pending-turn-context-fix--2348-Thinking-card-interim-text-echo-suppression) [Compare Source](nesquena/hermes-webui@v0.51.71...v0.51.72) ##### Fixed - **PR [#​2354](nesquena/hermes-webui#2354 by [@​franksong2702](https://github.com/franksong2702) (fixes [#​2353](nesquena/hermes-webui#2353)) — Stale stream recovery now keeps a recovered pending user turn in the model context (`context_messages`) as well as the visible transcript. Pre-fix, a server restart during an in-flight turn could restore the user's message in WebUI while omitting it from `context_messages`, so the next agent turn could forget a prompt that was visibly present just above it. The repair path now appends the recovered user turn to both surfaces with 8-message lookback dedup so already-checkpointed entries are not duplicated. - **PR [#​2348](nesquena/hermes-webui#2348 by [@​franksong2702](https://github.com/franksong2702) (fixes [#​2346](nesquena/hermes-webui#2346)) — Thinking cards now suppress exact snippets that are already shown as user-visible interim assistant text, avoiding duplicated progress lines when an agent emits the same sentence through both reasoning and interim-assistant callbacks. Tracks `_liveThinkingText` during the live stream to strip the visible echo from the live Thinking card display; applies the same suppression in the settled-transcript path so reload/session-switch sees the cleaned-up view too. ### [`v0.51.71`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05171--2026-05-16--Release-AU-stage-364--3-PR-batch--2349-stale-stream-cleanup-non-touching--2343-profiles-vs-workspaces-help-card--2283-run-event-journal-replay-refs-1925-RFC-slice-1--with-Opus-caught-replay-double-render-fix) [Compare Source](nesquena/hermes-webui@v0.51.70...v0.51.71) ##### Added - **PR [#​2343](nesquena/hermes-webui#2343 by [@​Michaelyklam](https://github.com/Michaelyklam) (refs [#​2147](nesquena/hermes-webui#2147)) — The Profiles panel now includes an inline "Profiles vs workspaces" explainer. The copy clarifies that profiles control how the agent works — identity, memory, skills, model/provider config, and tools — while workspaces control what project/files a session operates on, making the OpenClaw-style role/profile mental model easier to map onto Hermes WebUI. - **PR [#​2283](nesquena/hermes-webui#2283 by [@​franksong2702](https://github.com/franksong2702) (refs [#​1925](nesquena/hermes-webui#1925)) — Adds an append-only WebUI run event journal for browser-originated chat streams (refs [#​1925](nesquena/hermes-webui#1925)). Every SSE event emitted by the legacy in-process runner is mirrored to a per-session JSONL file, `/api/chat/stream/status` reports when replay is available for a dead stream, `/api/chat/stream` can replay journaled events with SSE event IDs and a clear stale-restart diagnostic, and the frontend reattach path uses that replay before clearing local running state. Reconnect replay uses the last rendered SSE event id as its `after_seq` cursor so it does not replay already-rendered events, and journal fsync defaults to terminal events only (`HERMES_WEBUI_RUN_JOURNAL_FSYNC=eager` restores per-event fsync). This is the first compatibility slice only: it preserves the existing WebUI runner and does not make active execution survive a WebUI restart. **Stage-364 maintainer fix applied inline**: Opus advisor caught that live SSE frames emitted by `_sse()` in `api/streaming.py:2296` carry no `id:` field, so the frontend's `_lastRunJournalSeq` cursor stayed at 0 during live streaming and a mid-stream error→replay would arrive with `after_seq=0`, replaying every journaled event from seq 1 and double-rendering tokens. The fix adds `STREAM_LAST_EVENT_ID: dict = {}` as a per-stream side-channel in `api/config.py`; `put()` writes the journal's `event_id` to that dict on every event; `_handle_sse_stream` reads it at SSE emit time and uses `_sse_with_id(handler, event, data, event_id)` when present. The queue tuple shape is preserved as `(event, data)` so existing queue consumers (cancel sentinel, sprint42/51 tests, etc.) are not broken. Cleaned up in the worker's finally block alongside the other STREAM\_\* dicts. 6 regression tests added covering side-channel dict declaration, writer/reader paths, tuple shape preservation, and cleanup. ##### Fixed - **PR [#​2349](nesquena/hermes-webui#2349 by [@​franksong2702](https://github.com/franksong2702) (fixes [#​2345](nesquena/hermes-webui#2345)) — Clearing stale stream runtime flags no longer refreshes a session's `updated_at`, so old compressed continuations should not jump back to the top of the sidebar just because WebUI repaired a dead `active_stream_id` during a read/list request. ### [`v0.51.70`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05170--2026-05-16--Release-AS-stage-363--4-PR-snapshotjournalUI-batch--2337-compression-snapshot-runtime-clear--2334-turn-journal-fcntl-lock--2342-INFLIGHT-reattach-pending-row--2339-workspace-panel-edge-toggle) [Compare Source](nesquena/hermes-webui@v0.51.69...v0.51.70) ##### Added - **PR [#​2339](nesquena/hermes-webui#2339 by [@​Michaelyklam](https://github.com/Michaelyklam) (refs [#​2211](nesquena/hermes-webui#2211)) — The workspace panel now has a small desktop edge toggle that remains clickable after the right panel is hidden, making it possible to reopen the workspace browser without returning to Settings. The existing panel close button and composer workspace button remain unchanged; the new affordance only appears when the workspace panel is closed on desktop widths. ##### Fixed - **PR [#​2337](nesquena/hermes-webui#2337 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2336](nesquena/hermes-webui#2336)) — Pre-compression snapshot preservation now also clears stale runtime stream fields when the existing on-disk snapshot is already as complete as the in-memory session. This keeps the load-and-mark branch aligned with the full-save branch and adds regression coverage so archived parent snapshots cannot retain stale `active_stream_id` / `pending_*` state. - **PR [#​2342](nesquena/hermes-webui#2342 by [@​franksong2702](https://github.com/franksong2702) (fixes [#​2341](nesquena/hermes-webui#2341)) — Reattaching to an active streaming session now keeps the user prompt that started the running turn visible. Pre-fix, reload/session-switch restore could hydrate from the browser's INFLIGHT stream cache while the backend still held the initiating prompt only as `pending_user_message`, so the transcript showed assistant Thinking/Tool activity without the user's just-submitted message. The restore path now merges that pending user row into the live transcript before rendering and updates the INFLIGHT cache, while duplicate suppression checks the current message array so final session payloads do not show the prompt twice. - **PR [#​2334](nesquena/hermes-webui#2334 by [@​Michaelyklam](https://github.com/Michaelyklam) (refs [#​2097](nesquena/hermes-webui#2097)) — Turn journal appends now take an advisory `flock` around each JSONL event write and fsync when Unix file locks are available. This keeps oversized submitted-message events from interleaving at the byte level if a future deployment runs multiple WebUI worker processes against the same state directory, while preserving the previous best-effort append path on platforms without `fcntl`. ### [`v0.51.69`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05169--2026-05-15--Release-AT-stage-362--8-PR-follow-up-batch--Ollama-routing--legacy-toolset--cancel-copy--cleanup--custom-provider-mismatch--cron-metadata--dead-code-removal-2323-reverted-after-Opus-caught-silent-regression-refiled-as-2321-reopen) [Compare Source](nesquena/hermes-webui@v0.51.68...v0.51.69) ##### Added - **PR [#​2332](nesquena/hermes-webui#2332 by [@​Michaelyklam](https://github.com/Michaelyklam) (refs [#​2290](nesquena/hermes-webui#2290)) — Cron run history/output cards now surface token/cost metadata when the underlying cron output markdown includes it. The backend parses optional model/token/cost/duration frontmatter from cron output files and returns it from `/api/crons/history` and `/api/crons/run`; the Tasks panel renders a compact usage strip beside run rows and below expanded output without affecting older outputs that lack usage metadata. ##### Fixed - **PR [#​2322](nesquena/hermes-webui#2322 by [@​Michaelyklam](https://github.com/Michaelyklam) (refs [#​2271](nesquena/hermes-webui#2271)) — LAN Ollama models selected from endpoint-discovered `custom:<host>-<port>` / `custom:<host>:<port>` picker entries now route through the configured `ollama` provider and base URL instead of surfacing a missing `CUSTOM_*_API_KEY` error. The picker still surfaces endpoint-discovered entries; the fix is to recognize them as UI routing hints matching the configured local-server base URL and resolve them via the actual `ollama` provider. - **PR [#​2326](nesquena/hermes-webui#2326 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2232](nesquena/hermes-webui#2232)) — Legacy `hermes` CLI toolset alias is now normalized to `hermes-cli` + `hermes-api-server` when WebUI resolves CLI toolsets from shared Hermes config. Modern Hermes Agent exposes the composite under those two names; older configs that still contain the legacy `hermes` toolset name no longer surface as "unknown toolset" warnings. - **PR [#​2327](nesquena/hermes-webui#2327 by [@​dotBeeps](https://github.com/dotBeeps) — Cancel-mid-stream messaging now uses the user's configured assistant name (e.g. "Hermes") instead of hardcoded "Skyly". Preferences allow defining an Assistant Name that persists throughout the UI; the cancel copy was the last place still showing the persona placeholder. Backend persisted-cancelled-turn text and frontend live-cancel toast both now read from the same `botName` setting. - **PR [#​2328](nesquena/hermes-webui#2328 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2325](nesquena/hermes-webui#2325)) — Two cleanup follow-ups from v0.51.68 stage-361 review: (a) when a session is deleted via `/api/session/delete`, its `~/.hermes/webui/attachments/<sid>/` inbox is also removed (orphan accumulation prevention); (b) the deferred stream-recovery listener bound by `_deferStreamErrorIfPageHidden()` now bails out when the user switches sessions in the same tab — the recovery would otherwise fire `setComposerStatus('Reconnected')` for a stream the user has moved past. Both fixes are narrow cleanup with regression tests. - **PR [#​2330](nesquena/hermes-webui#2330 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2329](nesquena/hermes-webui#2329)) — Provider mismatch warnings now skip named custom providers such as `custom:zenmux`. Custom aggregators can legitimately route vendor-prefixed models like `google/gemini-3.1-flash-lite`, so `_checkProviderMismatch()` now treats `custom:<name>` the same as bare `custom` and avoids false-positive "may not work with your configured provider" warnings. - **PR [#​2331](nesquena/hermes-webui#2331 by [@​Michaelyklam](https://github.com/Michaelyklam) — Live activity row now shows a transient human-readable progress phrase derived from the current tool category (e.g. "Reading file…", "Searching files…", "Running command…") instead of only the elapsed-time counter `Working 1m 23s`. Compact transcript view unchanged. - **PR [#​2333](nesquena/hermes-webui#2333 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2312](nesquena/hermes-webui#2312) follow-up [#​1](nesquena/hermes-webui#1)) — Removed dead production helper `_save_pre_compression_snapshot()` at `api/streaming.py:1945`. The production path now uses `_preserve_pre_compression_snapshot()` exclusively (which must index snapshots with `skip_index=False` for sidebar filtering). The dead helper was only called from `tests/test_compression_snapshot_runtime_clear.py`; the test is retargeted to exercise the actual production helper instead. Closes follow-up item [#​1](nesquena/hermes-webui#1) from the v0.51.66 review ([#​2312](nesquena/hermes-webui#2312)). ### [`v0.51.68`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05168--2026-05-15--Release-AR-stage-361--4-PR-follow-up-batch--2315-profile-skill-seeding--2317-theme-fallback--2318-mobile-stream-defer--2319-chat-upload-relocation--with-Opus-caught-vision-model-regression-fix) [Compare Source](nesquena/hermes-webui@v0.51.67...v0.51.68) ##### Added - **PR [#​2319](nesquena/hermes-webui#2319 by [@​Michaelyklam](https://github.com/Michaelyklam) — Chat file uploads now land in a session-scoped attachment inbox instead of cluttering the active workspace root. By default uploads are stored under `~/.hermes/webui/attachments/<session_id>/`; operators can override the root with `HERMES_WEBUI_ATTACHMENT_DIR`, and the agent still receives the absolute uploaded file path for context. Archive extraction stays workspace-scoped (it's an explicit workspace operation). README updated to document the new default location. **Stage-361 maintainer fix applied inline**: Opus advisor caught that `_build_native_multimodal_message` at `api/streaming.py:787` required uploads to be under `workspace_root`, which would have silently dropped every image upload for vision-capable models once the inbox moved outside the workspace. The fix adds `_attachment_root()` (from `api/upload.py`) as a second allowed location, with 3 regression tests covering the new code path AND verifying the original workspace + cross-root rejection paths still work. ##### Fixed - **PR [#​2315](nesquena/hermes-webui#2315 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2305](nesquena/hermes-webui#2305), refs [#​749](nesquena/hermes-webui#749)) — WebUI profile creation now seeds bundled profile skills for newly-created non-cloned profiles, matching the CLI's `hermes profile create` behaviour. Pre-fix, creating a profile via Settings → New Profile (without checking "Clone from active profile") left the profile's `skills/` directory empty, which was inconsistent with CLI-created profiles that get the full bundled-skills overlay. The fix calls `seed_profile_skills(profile_path, quiet=True)` after `profile_path.mkdir()` when `clone_from is None`. Cloned profiles still inherit skills from their source — they don't get a second bundled-skills overlay. Seed failures (e.g. `hermes_cli` unavailable in Docker fallback) are logged as warnings, not fatal — profile creation still succeeds. - **PR [#​2317](nesquena/hermes-webui#2317 by [@​Michaelyklam](https://github.com/Michaelyklam) (refs [#​2312](nesquena/hermes-webui#2312) follow-up [#​2](nesquena/hermes-webui#2)) — Appearance boot reconciliation now treats explicit `light`, `dark`, and `system` localStorage theme values as user selections when a prior Settings autosave failed. Pre-fix, the predicate `lsHasExplicitTheme = lsTheme === 'system'` only treated 'system' as explicit, so a user who picked `light` on a server defaulted to `dark` (or vice versa) with a failed autosave still reverted to the server default on refresh. Now broadened to `['system','light','dark'].includes(lsTheme)`. Skin handling was already correct (`lsSkin !== 'default'`). Closes follow-up item [#​2](nesquena/hermes-webui#2) from the v0.51.66 review ([#​2312](nesquena/hermes-webui#2312)). - **PR [#​2318](nesquena/hermes-webui#2318 by [@​Michaelyklam](https://github.com/Michaelyklam) (closes [#​2307](nesquena/hermes-webui#2307)) — Mobile/Android backgrounded tabs no longer show a permanent `**Error:** Connection lost` banner when the backend stream is still alive and able to replay buffered events. Pre-fix, the SSE error finalization fired regardless of page visibility state, so any tab discarded by the mobile OS (battery saver, tab compression, brief switch to another app) showed a permanent error even though the stream could be re-attached on visibility return. The fix defers inline stream error rendering while `document.visibilityState === 'hidden'` or `document.wasDiscarded === true`, then on visibility return polls `/api/chat/stream/status?stream_id=...`. If the stream is still active, reattaches with a fresh `EventSource`. If not, falls back to the settled-session restore path. If both paths fail, falls back to the original error rendering. Behaviour on desktop and on tabs that ARE visible is unchanged. </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/501
Seed bundled skills for WebUI profile creation (Michaelyklam, closes nesquena#2305) # Conflicts: # CHANGELOG.md
Seed bundled skills for WebUI profile creation (Michaelyklam, closes nesquena#2305) # Conflicts: # CHANGELOG.md
Summary
Closes #2305
Refs #749
Verification