Skip to content

feat: cap pinned sessions from sidebar - #2614

Merged
1 commit merged into
nesquena:masterfrom
Michaelyklam:feat/issue-2508-session-pin-cap
May 20, 2026
Merged

1 commit merged into
nesquena:masterfrom
Michaelyklam:feat/issue-2508-session-pin-cap

Conversation

@Michaelyklam

Copy link
Copy Markdown
Contributor

Thinking Path

  • Issue 会话里的对话内容 能提供置顶功能吗 #2508 clarified the requested first slice as session-level pinning from the sidebar, not message-level pins.
  • The WebUI already had a session pinned group and action-menu pin toggle, so the safest slice is to complete the requested workflow rather than introduce a parallel pinned-items surface.
  • The missing pieces were right-click access to the action menu and the requested three-pinned-session cap.
  • The cap needs to live in the backend as the source of truth, with a frontend guard only for clearer UX.

What Changed

  • Adds a backend guard to /api/session/pin that rejects a fourth active pinned conversation until one is unpinned.
  • Adds a frontend pinned-count guard and muted disabled menu styling for the pin action when the cap is reached.
  • Opens the existing session action menu from a right-click/context-menu gesture on session rows.
  • Adds regression coverage for the backend cap, frontend/source guard, disabled styling, and right-click menu hook.
  • Adds an Unreleased changelog entry.

Why It Matters

  • Matches the clarified 会话里的对话内容 能提供置顶功能吗 #2508 workflow: right-click a conversation, pin it, keep frequently used conversations in the pinned bucket, and keep the pinned area bounded.
  • Keeps pin state on the existing session model so it persists across reloads and devices through server-side session state.
  • Avoids a broad sidebar redesign or a duplicate pinning system.

Verification

  • env -u HERMES_CONFIG_PATH -u HERMES_WEBUI_HOST /home/michael/.hermes/hermes-agent/venv/bin/python -m pytest tests/test_issue2508_session_pin_cap.py tests/test_sprint12.py::test_pin_session tests/test_sprint12.py::test_unpin_session tests/test_sprint12.py::test_pinned_in_session_list tests/test_issue856_pinned_indicator_layout.py -q — 15 passed
  • env -u HERMES_CONFIG_PATH -u HERMES_WEBUI_HOST /home/michael/.hermes/hermes-agent/venv/bin/python -m py_compile api/routes.py
  • node --check static/sessions.js
  • git diff --check
  • Raw screenshot media verified HTTP 200.

UI Media

Pinned session sidebar

Risks / Follow-ups

  • This preserves the existing pinned group at the top of the sidebar rather than adding a new right-side panel. The reporter's mockup/comment described both a right-click workflow and display near the top/right; this PR keeps the change bounded to the existing sidebar architecture.
  • The cap ignores archived sessions so users can archive old pinned conversations without having them consume one of the three active pin slots.

Refs #2508

Model Used

AI-assisted change with repository inspection, targeted editing, and shell-based test verification.

@Michaelyklam
Michaelyklam force-pushed the feat/issue-2508-session-pin-cap branch from 0608c98 to 9ca846e Compare May 20, 2026 03:50
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Summary

Reviewed the diff at cron-pr-2614 against origin/master. The PR adds a 3-pin cap with a backend guard, frontend optimistic check, disabled-menu styling, and a right-click context-menu entry point — all four items the original reporter explicitly requested on #2508. CI is green on 3.11/3.12/3.13.

Backend cap

api/routes.py:5631-5650 (post-fix):

pin_requested = bool(body.get("pinned", True))
if pin_requested and not getattr(s, "pinned", False):
    pinned_ids = {
        getattr(existing, "session_id", None) for existing in all_sessions()
        if getattr(existing, "pinned", False) and not getattr(existing, "archived", False)
    }
    with LOCK:
        pinned_ids.update(
            sid for sid, existing in SESSIONS.items()
            if getattr(existing, "pinned", False) and not getattr(existing, "archived", False)
        )
    pinned_ids.discard(body["session_id"])
    if len(pinned_ids) >= 3:
        return bad(handler, "Up to 3 sessions can be pinned. ...", 400)

Two things to flag:

  1. all_sessions() is the right source. It already returns compact() dicts and the sort path at api/models.py:1655 ordered by (pinned, sort_ts). The compact dict at api/models.py:670-673 includes both pinned and archived, so the comprehension works. Good.

  2. The with LOCK overlay is necessary but subtle. all_sessions() overlays SESSIONS itself inside its own with LOCK block (api/models.py:1598-1603), so doing it again here is a belt-and-braces guard. It does ensure that an in-memory session not yet present in the index is still counted — defensive, no race against a concurrent pin call other than the LOCK serialising the read. Not wrong, but worth noting that the overlap means the comprehension runs the lock check twice on the same iteration. Cheap enough not to matter; the alternative (read inside all_sessions() only) would still be correct.

  3. Toggle-off has no guard, which is correct. Unpinning is always allowed, so a user who pinned a fourth session via a stale client can recover by unpinning rather than being deadlocked.

Frontend guards

static/sessions.js:1788-1810:

const pinLimitReached=!session.pinned&&_pinnedSessionCount()>=3;
menu.appendChild(_buildSessionAction(
  session.pinned?t('session_unpin'):t('session_pin'),
  pinLimitReached?'Only 3 conversations can be pinned':(session.pinned?t('session_unpin_desc'):t('session_pin_desc')),
  ...
  async()=>{
    closeSessionActionMenu();
    if(pinLimitReached){
      if(typeof showToast==='function') showToast('Only 3 conversations can be pinned. Unpin one before pinning another.',3000,'error');
      return;
    }
    ...
  },
  (session.pinned?'is-active':'')+(pinLimitReached?' is-disabled':'')
));

_pinnedSessionCount() at static/sessions.js:1478-1480 reads from _allSessions (the sidebar cache), so the count reflects what the user is looking at. If the cache is stale, the backend guard at api/routes.py:5647 still rejects the pin and returns 400. That's the right pattern — optimistic UI + authoritative server.

Right-click handler

static/sessions.js:3399-3408:

el.oncontextmenu=(e)=>{
  if(readOnly) return;
  e.preventDefault();
  e.stopPropagation();
  ...
  _openSessionActionMenu(s, actions||el);
};

The readOnly short-circuit is consistent with how the existing action button is conditionally hidden — read-only sessions don't get the action affordance at all. clearTimeout(_tapTimer); _tapTimer=null; _lastTapTime=0; _clearPointerDragState(); resets touch-double-tap state, which avoids the right-click + accidental-double-tap interaction described in the touch-device fallback comments later in the file. Solid.

Test coverage

tests/test_issue2508_session_pin_cap.py:42-66 runs against BASE (the pytest port) and exercises the actual HTTP endpoint, including the 400-on-4th-pin and the "unpin one to free a slot" workflow. The non-HTTP test_session_pin_cap_has_backend_and_frontend_guards and test_session_rows_open_action_menu_from_right_click are source-string snapshots — slightly brittle, but they guard against accidental removal of the cap check or the right-click handler in future refactors. Acceptable.

Recommendation

LGTM. Two nits worth considering for follow-up (not blocking):

  • The cap message uses both "Up to 3 sessions can be pinned" (backend) and "Only 3 conversations can be pinned" (frontend toast). Worth aligning the wording in a future polish pass.
  • The hard-coded 3 appears in api/routes.py:5647, static/sessions.js:1789, and the test. A MAX_PINNED_SESSIONS constant on the backend exposed via a small config or response field would let the frontend stay in sync if this is ever bumped to 5 or 10. Not worth blocking this PR over.

@nesquena-hermes nesquena-hermes closed this pull request by merging all changes into nesquena:master in 6c60925 May 20, 2026
dobby-d-elf pushed a commit to dobby-d-elf/hermes-webui that referenced this pull request May 20, 2026
# Conflicts:
#	CHANGELOG.md
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request May 20, 2026
… 0.51.96) (#593)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/nesquena/hermes-webui](https://github.com/nesquena/hermes-webui) | patch | `0.51.95` → `0.51.96` |

---

### Release Notes

<details>
<summary>nesquena/hermes-webui (ghcr.io/nesquena/hermes-webui)</summary>

### [`v0.51.96`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05196--2026-05-20--Release-BT-stage-389--8-PR-batch--IPv6-dashboard-link-normalization--configured-title-generation-provider-routing--sidebar-pinned-session-3-cap--external-refresh-sidecar-count-preference--Hermes-overview-docs-relocation--legacy-dedup-timestamp-granularity--custom-provider-models-endpoint-error-surfacing--RuntimeAdapter-Slice-4c-harness-gate-RFC)

[Compare Source](nesquena/hermes-webui@v0.51.95...v0.51.96)

##### Fixed

- **PR [#&#8203;2610](nesquena/hermes-webui#2610 by [@&#8203;AJV20](https://github.com/AJV20) — Preserve square brackets around IPv6 hosts when normalizing browser-only dashboard URLs, so links like `http://[::1]:9119` remain valid after saving instead of being mangled into invalid IPv6 forms. Closes the regression introduced by the URL-sanitization path added in [#&#8203;2533](nesquena/hermes-webui#2533) / v0.51.95 — bracketed IPv6 hosts now round-trip through the dashboard-link save flow unchanged.
- **PR [#&#8203;2612](nesquena/hermes-webui#2612 by [@&#8203;AJV20](https://github.com/AJV20) — Route WebUI session title generation through the configured `auxiliary.title_generation` provider, model, and base URL when present in config, instead of leaving the auxiliary client to silently fall back to the chat model. Users who configure a smaller/cheaper model for title generation (e.g. a fast 8B model on a separate provider) now have that selection honored end-to-end.
- **PR [#&#8203;2618](nesquena/hermes-webui#2618 by [@&#8203;LumenYoung](https://github.com/LumenYoung) — Prefer the persisted sidecar `message_count` over the session-index stored count during external-refresh polling. The metadata-only `/api/session?messages=0` path now reads `Session._metadata_message_count` when sidecar data is available, so legacy sessions whose state.db retains old rows still trip the external-refresh signal correctly on sidecar updates. Composes cleanly with [#&#8203;2604](nesquena/hermes-webui#2604) (the legacy-fallback only applies when the reconciled merged count is zero).
- **PR [#&#8203;2620](nesquena/hermes-webui#2620 by [@&#8203;bengdan](https://github.com/bengdan) — Use second-level timestamp granularity in the legacy message-dedup key. Drops the microsecond fallback in `_normalized_message_timestamp_for_dedup_key()` so transcripts that encode timestamps at different sub-second precisions (e.g. `"10.0"` vs `10.000000`) collapse to the same dedup bucket. Retroactively de-duplicates the dominant failure mode in [#&#8203;2616](nesquena/hermes-webui#2616) without requiring an on-disk session rewrite.
- **PR [#&#8203;2626](nesquena/hermes-webui#2626 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (closes [#&#8203;2540](nesquena/hermes-webui#2540)) — Surface named custom-provider `/models` endpoint failures in the model picker instead of silently showing an empty provider group. `_read_custom_endpoint_models` now returns `(models, error)`, so auth/network/HTTP failures propagate as structured `models_endpoint_error` hints on `/api/models` per affected provider. The composer model picker renders the hint as a quiet disabled-option diagnostic; configured fallback models remain selectable. 124 LOC of new regression coverage spans 401/network-error/5xx failure modes plus frontend hook validation.

##### Added

- **PR [#&#8203;2614](nesquena/hermes-webui#2614 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (refs [#&#8203;2508](nesquena/hermes-webui#2508)) — Cap sidebar-active pinned sessions at three. Right-clicking a conversation row opens the existing action menu, attempted pins beyond the cap render the menu item as disabled with an explanatory tooltip, and the backend rejects a fourth pin attempt with a structured error so the optimistic frontend can roll back the click. Settles the open question from [#&#8203;2508](nesquena/hermes-webui#2508) on whether pin count is bounded — the answer is three, configurable in a future PR if user demand surfaces.

##### Documentation

- **PR [#&#8203;2619](nesquena/hermes-webui#2619 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (closes [#&#8203;2595](nesquena/hermes-webui#2595)) — Move the long human-facing Hermes comparison document from root `HERMES.md` to `docs/why-hermes.md` so Hermes Agent sessions opened in this repository load `AGENTS.md` as the project-specific assistant guidance instead of the marketing overview. README links now point to the new docs path and a regression test (`tests/test_agent_context_docs.py`) prevents root `HERMES.md` / `.hermes.md` context files from silently reappearing.
- **PR [#&#8203;2627](nesquena/hermes-webui#2627 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (refs [#&#8203;1925](nesquena/hermes-webui#1925)) — Advance the RuntimeAdapter RFC after the Slice 4b `RunnerRuntimeAdapter` facade shipped in v0.51.94. The RFC now defines the next Slice 4c runner-backend harness gate: feature-flagged runner backend selection, explicit start payload validation, durable status/event observation across WebUI adapter recreation, bounded controls, and a deterministic harness for proving the facade's protocol-translation invariants without requiring the future runner/sidecar to exist.

</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/593
jakob1379 pushed a commit to jakob1379/hermes-webui that referenced this pull request May 21, 2026
…rable (builds on shipped nesquena#2614 3-cap)

Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request May 21, 2026
…➔ 0.51.105) (#613)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/nesquena/hermes-webui](https://github.com/nesquena/hermes-webui) | patch | `0.51.103` → `0.51.105` |

---

### Release Notes

<details>
<summary>nesquena/hermes-webui (ghcr.io/nesquena/hermes-webui)</summary>

### [`v0.51.105`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051105--2026-05-21--Release-CC-stage-398--4-PR-batch--hide-suggestions-preference--Docker-agent-version-from-copied-source--runner-local-adapter-selection--configurable-pinned-session-limit)

[Compare Source](nesquena/hermes-webui@v0.51.104...v0.51.105)

##### Added

- **PR [#&#8203;2687](nesquena/hermes-webui#2687 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (closes [#&#8203;2679](nesquena/hermes-webui#2679)) — Settings → Preferences gains a `Hide chat suggestions` toggle (config key `hide_empty_state_suggestions`). The empty new-chat screen normally shows three suggestion buttons as first-class tap targets, which causes accidental taps on mobile. Users who don't want the suggestions can hide them via the preference; the toggle persists across sessions and reloads. Default is OFF (suggestions remain visible) so existing users see no change.
- **PR [#&#8203;2700](nesquena/hermes-webui#2700 by [@&#8203;ai-ag2026](https://github.com/ai-ag2026) — Settings → Preferences gains a `Pinned conversations limit` numeric input. Builds on v0.51.96's [#&#8203;2614](nesquena/hermes-webui#2614) 3-cap by making the cap configurable (range 1–99, default 3, validated server-side via `_SETTINGS_INT_RANGES`). Backend validates the new cap on read, surfaces an error if a pin attempt would exceed it, and the right-click menu disables the pin item with an explanatory tooltip when the cap is reached. Default-3 keeps existing users on identical behavior.
- **PR [#&#8203;2696](nesquena/hermes-webui#2696 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) — RuntimeAdapter slice 4c — feature-flagged runner backend selection. The existing `HERMES_WEBUI_RUNTIME_ADAPTER` env var gains a new `runner-local` mode that wires up a `RunnerRuntimeAdapter` factory and adds a restart/reattach harness gate before the runner backend is used at the dispatcher. No user-visible change in this slice — unset / `legacy-direct` keeps existing behavior intact, and no production caller wires the new adapter yet. The slice exists so future work can land a sidecar runner without changing the runtime contract for existing users.

##### Fixed

- **PR [#&#8203;2703](nesquena/hermes-webui#2703 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (closes [#&#8203;2691](nesquena/hermes-webui#2691)) — System panel now detects the Hermes Agent version in Docker two-container deployments where the WebUI sees a copied Agent source volume instead of a live git checkout. The new detection cascade reads `VERSION` if present, falls back to the package metadata (`hermes_cli`), and finally to a `.git` describe if either is available, so the System panel reports the right version even when both `VERSION` and `.git` are absent in the copied source.

### [`v0.51.104`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v051104--2026-05-21--Release-CB-stage-397--9-PR-batch--i18n-zh-CNzh-TW-cron-status--geist-contrast-skin-polish--tablet-hardware-Enter--stale-Codex-slash-model-state--SSE-reconnect-jitter--cron-run-inline-expansion--inflight-send-race--new-chat-model-provider-sync--virtualized-sidebar-scroll-clamp-resync--transcript-cache-invalidation-on-same-count-content)

[Compare Source](nesquena/hermes-webui@v0.51.103...v0.51.104)

##### Fixed

- **PR [#&#8203;2690](nesquena/hermes-webui#2690 by [@&#8203;laiaman](https://github.com/laiaman) — Correct the zh-CN and zh-Hant translations for the `cron_status_active` label so it reads "enabled / scheduled" (`已启用` / `已啟用`) instead of "running" (`运行中` / `活躍中`). The English source is "active" (enabled, scheduled), and the prior Chinese strings conflated it with the separate `cron_status_running` "currently executing" state, making both labels look identical when a job was both scheduled and not currently firing.
- **PR [#&#8203;2701](nesquena/hermes-webui#2701 by [@&#8203;jasonjcwu](https://github.com/jasonjcwu) — Geist-contrast skin composer polish: force `--user-bubble-text` to `#111` in light mode so typed text is black on the light input background; hide the textarea scrollbar to match the rest of the skin; recolor the send button so it reads correctly against the contrast palette.
- **PR [#&#8203;2706](nesquena/hermes-webui#2706 by [@&#8203;dobby-d-elf](https://github.com/dobby-d-elf) — Tablet (iPad-class) devices with an attached hardware keyboard now send on Enter and newline on Shift+Enter, matching desktop behavior. The prior touch-primary check forced Enter→newline on every touch device, but tablets with hardware keyboards have a physical Shift key and should follow the desktop contract. Detection uses `matchMedia('(pointer:coarse)')` + a `window.visualViewport` height-delta probe (>120px shrink = software keyboard open) so an iPad with hardware keyboard (viewport not shrunk) treats Enter as send, while a phone tapping into the composer (soft keyboard shrinks the viewport) keeps Enter as newline. Falls back to the legacy touch behavior when `visualViewport` is unavailable.
- **PR [#&#8203;2684](nesquena/hermes-webui#2684 by [@&#8203;ai-ag2026](https://github.com/ai-ag2026) — Repair stale `openai/...` slash-qualified model IDs when the active/session provider is `openai-codex`. A stale browser/localStorage selection of `openai/gpt-5` against an `openai-codex` provider previously routed the chat to OpenAI directly instead of through Codex. The cross-provider model-switch resolver now detects the mismatch and re-resolves the model to the matching `codex/...` ID before the request goes out. Explicit OpenRouter slash-qualified selections continue to fast-path through unchanged.
- **PR [#&#8203;2671](nesquena/hermes-webui#2671 by [@&#8203;AJV20](https://github.com/AJV20) (closes [#&#8203;2629](nesquena/hermes-webui#2629) + [#&#8203;2661](nesquena/hermes-webui#2661)) — Session-list SSE reconnects now use bounded jitter/backoff (each retry delay is `base*0.75 + random*(base*0.35)` where `base = min(30000, 5000 * 2^attempt)`, capped at 30s) instead of a fixed 5-second retry, so tabs that all dropped at the same time (server restart, network drop) don't all retry in lockstep. Expanded cron run rows now render the full output inline immediately on click; the truncated preview remains only for collapsed rows, and the full-output fallback no longer drops content when Markdown rendering is unavailable.
- **PR [#&#8203;2689](nesquena/hermes-webui#2689 by [@&#8203;ai-ag2026](https://github.com/ai-ag2026) — Preserve the optimistic in-flight message array across the `/api/chat/start` await window so a fast back-to-back send doesn't clear the user's message before the stream ID arrives. The fix snapshots the inflight entry before the await, recreates it if a sidebar/session refresh pruned it during that window, and skips stale-inflight cleanup for the submitting session until a stream ID is bound. Regression test covers the race.
- **PR [#&#8203;2674](nesquena/hermes-webui#2674 by [@&#8203;AJV20](https://github.com/AJV20) — Resync the new-chat model picker when the server-created session has the same model ID as the current dropdown but a different provider. New conversations now resync to the configured default model provider instead of inheriting a stale persisted picker selection (e.g. `openai/gpt-5` from a previous session). Without this, the dropdown text matched the new session's model, but the provider attribute still pointed at the stale choice.
- **PR [#&#8203;2688](nesquena/hermes-webui#2688 by [@&#8203;ai-ag2026](https://github.com/ai-ag2026) — Resync the virtualized session sidebar after restoring a saved scroll position if the browser clamps or rejects that scroll position. Without this, date-group headers could render without their session rows beneath them until the user manually scrolled or a later refresh recomputed the virtual window. Regression test pins the recompute path.
- **PR [#&#8203;2692](nesquena/hermes-webui#2692 by [@&#8203;ai-ag2026](https://github.com/ai-ag2026) (refs [#&#8203;2613](nesquena/hermes-webui#2613)) — Invalidate the transcript render cache on same-count content changes, not just on count changes. The prior cache key was `(message_count, render_window_size)`, which silently reused a cached transcript whenever a same-count edit produced visibly different content (e.g. a tool retry that replaces a single assistant message with corrected text). The new cache signature folds a content hash into the key so any visible change forces a fresh render. Regression test asserts cache-bust on same-count content swap.

</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/613
SysAdminDoc pushed a commit to SysAdminDoc/hermes-webui that referenced this pull request Jun 26, 2026
# Conflicts:
#	CHANGELOG.md
SysAdminDoc pushed a commit to SysAdminDoc/hermes-webui that referenced this pull request Jun 26, 2026
SysAdminDoc pushed a commit to SysAdminDoc/hermes-webui that referenced this pull request Jun 26, 2026
…rable (builds on shipped nesquena#2614 3-cap)

Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
bernyforce pushed a commit to bernyforce/hermes-webui that referenced this pull request Jul 29, 2026
# Conflicts:
#	CHANGELOG.md
bernyforce pushed a commit to bernyforce/hermes-webui that referenced this pull request Jul 29, 2026
bernyforce pushed a commit to bernyforce/hermes-webui that referenced this pull request Jul 29, 2026
…rable (builds on shipped nesquena#2614 3-cap)

Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants