Skip to content

fix: guard new conversation cold-start clicks - #2528

Merged
1 commit merged into
nesquena:masterfrom
Michaelyklam:fix/issue-2518-new-session-inflight
May 18, 2026
Merged

1 commit merged into
nesquena:masterfrom
Michaelyklam:fix/issue-2518-new-session-inflight

Conversation

@Michaelyklam

@Michaelyklam Michaelyklam commented May 18, 2026

Copy link
Copy Markdown
Contributor

Thinking Path

  • The issue reports a cold-start path where POST /api/session/new waits behind model/provider catalog resolution.
  • During that wait, the sidebar + button gives no durable pending state, so repeated clicks can enqueue multiple blank sessions.
  • A narrow frontend guard can preserve the current backend behavior while making the interaction explicit and idempotent.

What Changed

  • Added a single in-flight newSession() promise so repeated New Conversation triggers reuse the same create request until it settles.
  • Disabled the sidebar New Conversation button with aria-busy="true" while creation is pending.
  • Shows a localized composer status message (Creating new conversation…) during the cold-create window.
  • Added source-level regression coverage and a release-note entry.

Why It Matters

This makes the button feel responsive during cold model/provider catalog resolution and prevents accidental duplicate blank sessions from rapid repeated clicks.

Closes #2518

Verification

  • env -u HERMES_CONFIG_PATH -u HERMES_WEBUI_HOST /home/michael/.hermes/hermes-agent/venv/bin/python -m pytest tests/test_issue2518_new_session_inflight.py tests/test_1432_newchat_and_1423_profile_input.py tests/test_profile_default_workspace_823.py -q — 20 passed
  • env -u HERMES_CONFIG_PATH -u HERMES_WEBUI_HOST /home/michael/.hermes/hermes-agent/venv/bin/python -m pytest tests/test_issue2518_new_session_inflight.py tests/test_chinese_locale.py tests/test_japanese_locale.py tests/test_korean_locale.py tests/test_russian_locale.py tests/test_spanish_locale.py -q — 29 passed
  • node --check static/sessions.js
  • node --check static/i18n.js
  • git diff --check
  • Isolated local WebUI screenshot pass on 127.0.0.1:18818

UI Media

Before / idle New Conversation button:

Idle New Conversation button

After / pending create state:

Pending New Conversation state

Risks / Follow-ups

  • This does not speed up cold provider/model catalog resolution itself; it only makes session creation idempotent and visibly pending while that work completes.
  • Other callers of newSession() intentionally share the same in-flight promise, so a slash command or shortcut fired during the pending window will land on the same new session rather than creating another duplicate.

Model Used

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

@Michaelyklam
Michaelyklam force-pushed the fix/issue-2518-new-session-inflight branch from 41baac4 to aeef101 Compare May 18, 2026 13:45
@nesquena-hermes

Copy link
Copy Markdown
Collaborator

Summary

Reading static/sessions.js:420-520 on this branch against origin/master, and the regression test at tests/test_issue2518_new_session_inflight.py, the fix correctly coalesces concurrent newSession() calls behind a single in-flight promise and adds a couple of nice UX touches the other open #2518 PR doesn't have: a localized Creating new conversation… composer status message (with i18n keys added for the supported locales) and a short toast when the user re-clicks during the pending window.

The shape — module-level _newSessionInFlight, a _setNewSessionPending(true/false) helper that drives both the button state and the composer status, wrapping the existing body in an IIFE so the final try/finally always runs — matches the contract the issue describes.

Code reference

Guard entry/exit at static/sessions.js:435-516 (this branch):

async function newSession(flash, options={}){
  if(_newSessionInFlight){
    if(typeof showToast==='function') showToast(_newSessionPendingText(),1500);
    return _newSessionInFlight;
  }
  _setNewSessionPending(true);
  _newSessionInFlight=(async()=>{
    // ... existing create body
  })();
  try{
    return await _newSessionInFlight;
  }finally{
    _newSessionInFlight=null;
    _setNewSessionPending(false);
  }
}

The composer-status helper at :420-434 is careful to only clear the status if it still matches the pending text — so a setComposerStatus() call from inside the create body (e.g. for a model-default warning) won't get nuked by the cleanup:

function _setNewSessionPending(pending){
  // ...
  const pendingText=_newSessionPendingText();
  if(pending){
    setComposerStatus(pendingText);
  }else if(statusEl&&statusEl.textContent===pendingText){
    setComposerStatus('');
  }
}

That's a good detail — it avoids racing against legitimate status writes from the inner block.

Diagnosis / Recommendation

The change is structurally fine. A few notes:

1. Overlap with PR #2519. That PR is open against the same issue and also lands a module-level promise + disabled / aria-busy / is-loading button state on btnNewChat. The two PRs touch the same function body and will conflict on merge. The maintainer will pick one. The differentiators worth weighing:

  • This PR has localized composer-status text and a re-click toast — better user feedback during slow cold starts.
  • fix: guard concurrent New Conversation creates #2519 has a Node runtime test that actually executes sessions.js and proves overlapping newSession() calls produce a single fetch — a stronger contract than the static source-string check here.

Neither is strictly superior. Either way, both fixes shouldn't land.

2. The static test at tests/test_issue2518_new_session_inflight.py is structural only. It greps for _newSessionInFlight and the pending-text token in the source. That catches accidental removal but doesn't verify the runtime behavior (single fetch under concurrent calls, button state actually toggles). If the maintainer prefers stronger contracts, this is the gap relative to #2519's runtime harness.

3. The await/finally placement is correct. return await _newSessionInFlight inside a try ensures the rejection from the inner promise propagates and the cleanup runs — equivalent to wrapping the body in try { ... } finally { cleanup() } directly. The IIFE pattern adds an extra microtask, which is fine here.

4. No error toast on rejection. If api('/api/session/new') rejects (network failure, cold provider catalog hits a 5xx), the user sees the busy state clear with no signal beyond the re-enabled button — the composer-status message disappears silently. The pending toast covers re-click during the pending window, but a catch toast inside the IIFE would close the loop for failed creates. Minor; not a blocker.

Verification

The CHANGELOG entry is release-note-ready. The i18n keys (new_session_creating) appear consistently in the locales touched by the diff. The screenshots in docs/pr-media/2518/ demonstrate the visible idle → pending transition. The change to static/style.css is the two-line disabled-state polish.

The main open question is the coordination with #2519. Both PRs are correct fixes; the issue is they shouldn't both land.

@nesquena-hermes nesquena-hermes closed this pull request by merging all changes into nesquena:master in 4589dbe May 18, 2026
Charanis pushed a commit to Charanis/hermes-webui-beyond that referenced this pull request May 18, 2026
# Conflicts:
#	CHANGELOG.md
eleboucher pushed a commit to eleboucher/homelab that referenced this pull request May 18, 2026
… 0.51.90) (#556)

This PR contains the following updates:

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

---

### Release Notes

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

### [`v0.51.90`](https://github.com/nesquena/hermes-webui/blob/HEAD/CHANGELOG.md#v05190--2026-05-18--Release-BN-stage-383--10-PR-full-sweep-batch--empty-gateway-messaging-history-fix--previous-messaging-sessions-setting--Kanban-board-switcher-layout--UIUX-demo-theme-controls--Slice-3c-queuegoal-RFC-gate--keyless-custom-endpoints--custom-provider-remote-model-catalog-parity--auto-compression-elapsed-timer--new-conversation-cold-start-guard--Kanban-drag-drop-detail-open-fix)

[Compare Source](nesquena/hermes-webui@v0.51.89...v0.51.90)

##### Fixed

- **PR [#&#8203;2286](nesquena/hermes-webui#2286 by [@&#8203;junjunjunbong](https://github.com/junjunjunbong) (refs [#&#8203;2275](nesquena/hermes-webui#2275)) — Narrow messaging stale-session filtering to active gateway sessions that are visible in the current sidebar candidate set. Older Discord/messaging history is now preserved when the gateway advertises a fresh zero-message session that hasn't yet entered the visible projection, instead of being hidden as stale. Adds a regression test for an empty active Discord gateway row preserving prior history.
- **PR [#&#8203;2459](nesquena/hermes-webui#2459 by [@&#8203;franksong2702](https://github.com/franksong2702) (closes [#&#8203;2458](nesquena/hermes-webui#2458)) — Fix the Kanban board switcher menu when a board's icon slot carries a long text label (e.g. `layout-kanban`). The icon column changed from a fixed `18px` slot to a bounded flex cell with `min-width:18px;max-width:7.5rem`, with overflow ellipsis on the icon itself so long labels render fully when space allows and truncate cleanly when not. Title and count columns keep stable spacing. Adds before/after screenshots and a CSS contract regression in `tests/test_kanban_ui_static.py`.
- **PR [#&#8203;2522](nesquena/hermes-webui#2522 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (refs [#&#8203;2271](nesquena/hermes-webui#2271)) — Treat named custom OpenAI-compatible endpoints with a configured `base_url` as key-optional at WebUI agent startup. Local keyless servers (llama-server / vLLM-style LAN deployments) no longer fail early with a synthetic `CUSTOM:<slug>_API_KEY` env-var prompt before the request reaches the endpoint; instead the OpenAI-compatible client initialises with a harmless placeholder key and real configured keys are still preferred when present. Refactors the three near-identical custom-provider rebuild blocks (initial agent setup + two retry/healing paths) through the existing `resolve_custom_provider_connection` helper.
- **PR [#&#8203;2515](nesquena/hermes-webui#2515 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (closes [#&#8203;2513](nesquena/hermes-webui#2513)) — Keep named custom-provider model pickers populated from each configured endpoint's live `/models` catalog even when `custom_providers[].model` is present. The singular `model` field now acts as a sticky/fallback entry appended *after* the remote catalog rather than collapsing the picker to just the configured model and hiding sibling named custom providers. Extracts reusable OpenAI-compatible `/models` parsing/fetching helpers and threads them through both the active-base-url and per-named-provider paths.
- **PR [#&#8203;2512](nesquena/hermes-webui#2512 by [@&#8203;dso2ng](https://github.com/dso2ng) (refs [#&#8203;2477](nesquena/hermes-webui#2477), Slice A) — Show an elapsed timer on the running automatic-compression card so long WebUI context-compression pauses no longer look frozen while the browser waits for the `compressed` event. Stamps `startedAt` on the `compressing` SSE event, ticks once per second, and switches to a `5+ min` cap label past the Slice A bound so the UI never frame-freezes at `05:00`. Browser-transient state only — no SSE contract change and no server-side resume reconstruction.
- **PR [#&#8203;2528](nesquena/hermes-webui#2528 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (closes [#&#8203;2518](nesquena/hermes-webui#2518)) — Guard New Conversation creation while a previous `/api/session/new` request is still in flight, so cold model/provider catalog resolution gives immediate pending feedback and rapid repeated clicks reuse the same create request instead of enqueueing duplicate blank sessions. Coalesces concurrent `newSession()` calls behind a single in-flight promise, disables the sidebar button with `aria-busy="true"`, and shows a localized `Creating new conversation…` composer status.
- **PR [#&#8203;2530](nesquena/hermes-webui#2530 by [@&#8203;franksong2702](https://github.com/franksong2702) (refs [#&#8203;2529](nesquena/hermes-webui#2529)) — Keep Kanban drag/drop status updates from also opening the task detail pane. Two failure paths were both producing detail-pane opens after drag/drop: the browser's trailing synthetic click after `drop`, and the generic task-update helper opening detail on every PATCH. The fix adds a time-windowed `_kanbanSuppressCardClickUntil` set on `ondragstart`/`ondragend`/`ondrop` and routes drag/drop status changes through a board-only update path. Explicit card click and keyboard activation remain unchanged.

##### Added

- **PR [#&#8203;2294](nesquena/hermes-webui#2294 by [@&#8203;junjunjunbong](https://github.com/junjunjunbong) — Add a `show_previous_messaging_sessions` setting so users can opt back into seeing previous messaging sessions that were replaced by `session_reset` or auto-compression. The preference is wired through boot, settings persistence, and the sidebar projection. Also adds a separate "Hide from list" action for imported messaging/CLI sessions that hides individual rows from the sidebar without deleting source history.

##### Documentation

- **PR [#&#8203;2511](nesquena/hermes-webui#2511 by [@&#8203;franksong2702](https://github.com/franksong2702) (refs [#&#8203;2502](nesquena/hermes-webui#2502) / [#&#8203;2503](nesquena/hermes-webui#2503)) — Update the `docs/ui-ux/` demo appearance controls to initialize as `class="dark" data-skin="slate"` instead of the deprecated `data-theme`-only buttons and legacy theme names. Brings the demo pages in line with the live Theme + Skin contract referenced from the new `docs/CONTRACTS.md` so contributors following the contract-index path don't land on stale demos.
- **PR [#&#8203;2509](nesquena/hermes-webui#2509 by [@&#8203;Michaelyklam](https://github.com/Michaelyklam) (refs [#&#8203;1925](nesquena/hermes-webui#1925)) — Advance the runtime-adapter RFC after the Slice 3b approval/clarify seam shipped in v0.51.89. The RFC now marks Slice 3b as shipped and defines the next Slice 3c queue/continue + goal control gate: route those controls through `RuntimeAdapter.queue_message(...)` / `update_goal(...)` only after pinning stable response contracts, bounded unavailable-control behavior, replayable lifecycle/status evidence, ordering/idempotency expectations, and explicit non-goals for runner/sidecar ownership or a WebUI-owned queue/goal scheduler. Docs + adapter-seam regression test only — no runtime/control routing changes in this PR.

</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/556
franksong2702 added a commit to franksong2702/hermes-webui-fork that referenced this pull request Jun 2, 2026
…#2518 follow-up)

The frontend in-flight guard (PR nesquena#2528) made repeated + clicks safe but
left a single cold click waiting 3-4s behind get_available_models():

  newSession() carried the dropdown's model_provider as
  reqBody.model_provider. When the dropdown option has no data-provider
  attribute (or its value is 'default') and the persisted state predates
  provider tracking, newModelState.model_provider is null. The server's
  fast path in _resolve_compatible_session_model_state requires both
  model AND a truthy model_provider; without that, the request falls
  into the cold catalog rebuild. The catalog warms after the first
  response, so subsequent clicks are fast.

newSession() now falls back through a 3-step chain:

  1. newModelState.model_provider (explicit picker)
  2. window._activeProvider (boot-hydrated active route)
  3. S.session.model_provider (previous session)

Whenever a usable default exists, the request hits the server's fast
path and stays out of get_available_models() entirely. The slow path
remains the safety net for genuinely provider-less clients.

Closes the open follow-up from nesquena#2518.

Tests:
- tests/test_issue2518_active_provider_fallback.py (new, 7 cases):
  source shape (fallback present, prev-session present, chain order,
  issue reference) + end-to-end (fast path on real + slow path still
  fires without provider).
- tests/test_new_chat_default_model_frontend.py: rewrote
  test_new_session_posts_picker_model_before_server_default from a
  literal-string snapshot into a behavior-contract assertion (chain
  members + ordering), per AGENTS.md change-detector guidance.
franksong2702 added a commit to franksong2702/hermes-webui-fork that referenced this pull request Jun 2, 2026
…#2518 follow-up)

The frontend in-flight guard (PR nesquena#2528) made repeated + clicks safe but
left a single cold click waiting 3-4s behind get_available_models():

  newSession() carried the dropdown's model_provider as
  reqBody.model_provider. When the dropdown option has no data-provider
  attribute (or its value is 'default') and the persisted state predates
  provider tracking, newModelState.model_provider is null. The server's
  fast path in _resolve_compatible_session_model_state requires both
  model AND a truthy model_provider; without that, the request falls
  into the cold catalog rebuild. The catalog warms after the first
  response, so subsequent clicks are fast.

newSession() now falls back through a 3-step chain:

  1. newModelState.model_provider (explicit picker)
  2. window._activeProvider (boot-hydrated active route)
  3. S.session.model_provider (previous session)

Whenever a usable default exists, the request hits the server's fast
path and stays out of get_available_models() entirely. The slow path
remains the safety net for genuinely provider-less clients.

Closes the open follow-up from nesquena#2518.

Tests:
- tests/test_issue2518_active_provider_fallback.py (new, 7 cases):
  source shape (fallback present, prev-session present, chain order,
  issue reference) + end-to-end (fast path on real + slow path still
  fires without provider).
- tests/test_new_chat_default_model_frontend.py: rewrote
  test_new_session_posts_picker_model_before_server_default from a
  literal-string snapshot into a behavior-contract assertion (chain
  members + ordering), per AGENTS.md change-detector guidance.
franksong2702 added a commit to franksong2702/hermes-webui-fork that referenced this pull request Jun 3, 2026
…#2518 follow-up)

The frontend in-flight guard (PR nesquena#2528) made repeated + clicks safe but
left a single cold click waiting 3-4s behind get_available_models():

  newSession() carried the dropdown's model_provider as
  reqBody.model_provider. When the dropdown option has no data-provider
  attribute (or its value is 'default') and the persisted state predates
  provider tracking, newModelState.model_provider is null. The server's
  fast path in _resolve_compatible_session_model_state requires both
  model AND a truthy model_provider; without that, the request falls
  into the cold catalog rebuild. The catalog warms after the first
  response, so subsequent clicks are fast.

newSession() now falls back through a 3-step chain:

  1. newModelState.model_provider (explicit picker)
  2. window._activeProvider (boot-hydrated active route)
  3. S.session.model_provider (previous session)

Whenever a usable default exists, the request hits the server's fast
path and stays out of get_available_models() entirely. The slow path
remains the safety net for genuinely provider-less clients.

Closes the open follow-up from nesquena#2518.

Tests:
- tests/test_issue2518_active_provider_fallback.py (new, 7 cases):
  source shape (fallback present, prev-session present, chain order,
  issue reference) + end-to-end (fast path on real + slow path still
  fires without provider).
- tests/test_new_chat_default_model_frontend.py: rewrote
  test_new_session_posts_picker_model_before_server_default from a
  literal-string snapshot into a behavior-contract assertion (chain
  members + ordering), per AGENTS.md change-detector guidance.
franksong2702 pushed a commit to franksong2702/hermes-webui-fork that referenced this pull request Jun 3, 2026
…llback

Closes the open follow-up from nesquena#2518 - addresses the cross-provider
regression flagged in PR nesquena#3410 review: when the persisted state carries
a stale foreign-slug model (e.g. "gemini/gemini-2.5") from a session
served by a different provider than the now-active one, the
window._activeProvider fallback would attach the wrong provider and
let _resolve_compatible_session_model_state's fast path pass it through
without consulting the catalog - silently re-pointing the new session
at the wrong backend.

The new client guard wraps the active-provider fallback in a
_bareModel ternary (rejects '/' and '@' prefixes) so slash-qualified
and @-qualified models keep model_provider=null on the wire and the
slow path's cross-provider normalization still runs. Also drops a
vestigial mid-chain '||null' no-op.

Adds 6 regression tests in test_issue2518_active_provider_fallback.py
(test_slash_qualified_model_keeps_active_provider_behind_guard,
test_at_qualified_model_also_keeps_active_provider_behind_guard,
test_explicit_picker_provider_still_wins,
test_no_op_null_terminal_in_fallback_chain,
test_slash_slug_keeps_provider_null_in_wire_shape,
test_bare_model_uses_active_provider_when_no_picker). Behavior-contract
assertions, not source-string pins, so future refactors of the same
contract still satisfy them.

Builds on nesquena#2528 (in-flight guard) and nesquena#1855 (fast path).
PR body draft: docs/pr-media/2518/PR_BODY.md
franksong2702 added a commit to franksong2702/hermes-webui-fork that referenced this pull request Jun 3, 2026
…#2518 follow-up)

The frontend in-flight guard (PR nesquena#2528) made repeated + clicks safe but
left a single cold click waiting 3-4s behind get_available_models():

  newSession() carried the dropdown's model_provider as
  reqBody.model_provider. When the dropdown option has no data-provider
  attribute (or its value is 'default') and the persisted state predates
  provider tracking, newModelState.model_provider is null. The server's
  fast path in _resolve_compatible_session_model_state requires both
  model AND a truthy model_provider; without that, the request falls
  into the cold catalog rebuild. The catalog warms after the first
  response, so subsequent clicks are fast.

newSession() now falls back through a 3-step chain:

  1. newModelState.model_provider (explicit picker)
  2. window._activeProvider (boot-hydrated active route)
  3. S.session.model_provider (previous session)

Whenever a usable default exists, the request hits the server's fast
path and stays out of get_available_models() entirely. The slow path
remains the safety net for genuinely provider-less clients.

Closes the open follow-up from nesquena#2518.

Tests:
- tests/test_issue2518_active_provider_fallback.py (new, 7 cases):
  source shape (fallback present, prev-session present, chain order,
  issue reference) + end-to-end (fast path on real + slow path still
  fires without provider).
- tests/test_new_chat_default_model_frontend.py: rewrote
  test_new_session_posts_picker_model_before_server_default from a
  literal-string snapshot into a behavior-contract assertion (chain
  members + ordering), per AGENTS.md change-detector guidance.
franksong2702 pushed a commit to franksong2702/hermes-webui-fork that referenced this pull request Jun 3, 2026
…llback

Closes the open follow-up from nesquena#2518 - addresses the cross-provider
regression flagged in PR nesquena#3410 review: when the persisted state carries
a stale foreign-slug model (e.g. "gemini/gemini-2.5") from a session
served by a different provider than the now-active one, the
window._activeProvider fallback would attach the wrong provider and
let _resolve_compatible_session_model_state's fast path pass it through
without consulting the catalog - silently re-pointing the new session
at the wrong backend.

The new client guard wraps the active-provider fallback in a
_bareModel ternary (rejects '/' and '@' prefixes) so slash-qualified
and @-qualified models keep model_provider=null on the wire and the
slow path's cross-provider normalization still runs. Also drops a
vestigial mid-chain '||null' no-op.

Adds 6 regression tests in test_issue2518_active_provider_fallback.py
(test_slash_qualified_model_keeps_active_provider_behind_guard,
test_at_qualified_model_also_keeps_active_provider_behind_guard,
test_explicit_picker_provider_still_wins,
test_no_op_null_terminal_in_fallback_chain,
test_slash_slug_keeps_provider_null_in_wire_shape,
test_bare_model_uses_active_provider_when_no_picker). Behavior-contract
assertions, not source-string pins, so future refactors of the same
contract still satisfy them.

Builds on nesquena#2528 (in-flight guard) and nesquena#1855 (fast path).
PR body draft: docs/pr-media/2518/PR_BODY.md
SysAdminDoc pushed a commit to SysAdminDoc/hermes-webui that referenced this pull request Jun 26, 2026
# Conflicts:
#	CHANGELOG.md
bernyforce pushed a commit to bernyforce/hermes-webui that referenced this pull request Jul 29, 2026
# Conflicts:
#	CHANGELOG.md
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.

New Conversation button appears unresponsive during cold model catalog resolution

2 participants