Commit Graph
100 Commits
Author SHA1 Message Date
nesquena-hermesandrodboev 63d0c00f8d harden #5504 on rodboev's latest head: complete the tombstone wiring + CHANGELOG
@rodboev independently pushed fixes for messaging-tombstone (matches ours) and an
audit orphan-.bak skip — but the audit skip used _marks_deleted_webui_session
(index heuristic), which re-introduces the crash-suppression bug, and the other 4
resurrection/recovery paths were still open. Rebuilt the stage on rodboev's new
head (fc21c3f3, attribution preserved) and applied the complete superset:

- routes.py claim path: tombstone 404 gated on _state_db_session_source in
  ('','webui','fork') so foreign-source rows always materialize (finding B)
- models.py sidebar projection: skip tombstoned source='webui' rows w/ no live
  sidecar so a deleted session can't resurface in /api/sessions (finding C)
- session_recovery.py orphan-.bak startup: skip restore when durable tombstone
  present, durable-only (finding D)
- session_recovery.py audit orphan-.bak: durable-only classify as
  deleted_session_skipped (corrects rodboev's index-heuristic version)
- session_recovery.py _read_state_db_missing_sidecar_rows: durable-tombstone-only
  so a genuine crash (index intact, no durable tombstone) still repairs (finding F)

Regression tests (all verified fail-without-fix): sidebar-projection, orphan-.bak
startup skip, messaging-not-tombstoned, index-only-crash-repairable. Both advisors
(Codex SAFE TO SHIP + Opus ship-with-fixes) cleared the prior stage; this rebuild
carries the same fixes onto the contributor's latest work.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-04 05:32:51 +00:00
nesquena-hermes 06217c93b8 Merge commit 'fc21c3f38e56' into release/stage-5504 2026-07-04 05:25:04 +00:00
nesquena-hermes 4f8bd1ef38 docs(changelog): #5487 stray-pointerup session-switch guard + #5458 IPv4-first gallery 2026-07-04 03:54:11 +00:00
nesquena-hermes fe30f1ff00 Merge PR #5458 from rumotoshino: prefer IPv4 for extension gallery downloads 2026-07-04 03:39:19 +00:00
nesquena-hermes fcd3de7d8f Merge PR #5487 from webtecnica: prevent unintended session switch on stray pointerup (#5462) 2026-07-04 03:39:18 +00:00
nesquena-hermes e874fc4149 docs(changelog): #5460 replace cross-profile empty sessions on profile switch 2026-07-04 03:33:06 +00:00
nesquena-hermes dbf3c9d3c0 Merge PR #5460 from ruizanthony: replace cross-profile empty sessions on profile switch 2026-07-04 03:05:45 +00:00
nesquena-hermes 8b6ababf8c docs(changelog): #5496 refresh dictation recognition.lang after locale change (#5483) 2026-07-04 02:42:56 +00:00
nesquena-hermes 091103cf6d Merge PR #5496 from webtecnica: refresh recognition.lang before dictation start (#5483) 2026-07-04 02:41:01 +00:00
nesquena-hermes 378548b566 docs(changelog): #5480 stale WebUI client recovery banner (#5428) 2026-07-04 01:28:02 +00:00
nesquena-hermes 568d5c4b0e gate-fix #5480: suppress 'unknown' server version (case-insensitive) to prevent false banner
Codex gate: _normalizeWebUIVersion suppressed empty/__WEBUI_VERSION__/'not detected'
but NOT 'unknown' — api/updates.py emits WEBUI_VERSION='unknown' on git-describe
failure (Docker/CI images), so a real client version would falsely fire the
stale-client banner against server='unknown'. Suppress 'unknown' (+ case-insensitive
for all sentinels). + regression test asserting unknown/UNKNOWN/Unknown don't fire.
2026-07-04 01:15:26 +00:00
nesquena-hermes b04f0387c4 Merge PR #5480 from rodboev: surface stale WebUI client recovery (#5428) 2026-07-04 01:09:14 +00:00
nesquena-hermes 8b1109a079 docs(changelog): #5452 fit fullscreen Mermaid to lightbox (#5413) 2026-07-04 00:17:07 +00:00
nesquena-hermes 0eb80f6197 Merge PR #5452 from rodboev: fit fullscreen Mermaid diagrams to the lightbox (#5413) 2026-07-04 00:07:04 +00:00
nesquena-hermes 8d9d37c118 Merge remote-tracking branch 'origin/master' into release/stage-5467
# Conflicts:
#	CHANGELOG.md
2026-07-03 23:44:49 +00:00
nesquena-hermes ed508ff6ef Merge remote-tracking branch 'origin/master' into release/stage-5467
# Conflicts:
#	CHANGELOG.md
2026-07-03 23:39:31 +00:00
nesquena-hermesandwebtecnica 329e911327 fix: prevent unintended session switch on stray pointerup (#5462)
Clean rebase of webtecnica's #5487 (rebase-first).

Co-authored-by: webtecnica <webtecnica@users.noreply.github.com>
2026-07-03 23:34:37 +00:00
nesquena-hermes f66944d006 docs(changelog): #5467 sidebar render-skip on idle polls (#5455) 2026-07-03 23:23:20 +00:00
nesquena-hermes a53c183dd5 fix(test): widen _applySessionListPayload slice to reach _mustForceRender assertion 2026-07-03 23:05:03 +00:00
nesquena-hermes b438976507 gate-fix #5467 r2: force render when recovering from skeleton/error-banner DOM
Codex re-gate found 2 more false-skips (DOM state OUTSIDE the signature path):
- CORE: profile-switch skeleton stays visible if the new payload signature
  matches the last one (empty/same-shaped profile) — skip fires over the skeleton.
- SILENT: stale 'Could not load conversations' banner persists when a transient
  fetch failure heals with identical rows.
Fix: capture _hadSessionListSkeleton + _hadSessionListLoadError BEFORE clearing
them, and disallow the identical-signature skip when either was set. + regression
test. (messages.js:1462 finding is a base-comparison artifact for #5472/#5479/#5484,
not in #5467's diff.)
2026-07-03 23:04:41 +00:00
nesquena-hermes 3999418b0e gate-fix #5467: serialize full rows in render-skip signature (close false-skips)
Codex gate found the render-skip signature omitted fields the sidebar renders:
- CORE: pending/running (active_stream_id/has_pending_user_message/pending_started_at)
- SILENT: attention dots
- SILENT: source/read-only/worktree/lineage/child/model/profile + _sidebarReferenceSessions
Any omitted field = a false-skip = stale sidebar.

Root-cause fix (most reliable): serialize the FULL applied row objects +
_sidebarReferenceSessions instead of a hand-picked allowlist — inherently
complete, can't rot when a new rendered field is added. Rewrote the
'ignores non-display fields' test into positive full-serialization + no-strip
regression assertions.
2026-07-03 22:58:21 +00:00
nesquena-hermes 10e5e941d3 Merge PR #5467 from ai-ag2026: skip full session-list rebuild when payload unchanged (#5455) 2026-07-03 22:47:40 +00:00
nesquena-hermes 8db6ec1536 Merge remote-tracking branch 'origin/master' into release/stage-5469 2026-07-03 22:32:54 +00:00
nesquena-hermes f18b384a2f docs(changelog): #5469 desktop scroll-anchor recover via sessionIdx 2026-07-03 22:32:53 +00:00
nesquena-hermes 3053b6522b docs(changelog): #5438 preset cron schedule builder (#5427) 2026-07-03 22:25:50 +00:00
nesquena-hermes e81711d3a9 Merge PR #5469 from allenliang2022: recover viewport anchor via sessionIdx (desktop scroll jump-back) 2026-07-03 22:18:17 +00:00
nesquena-hermes 5cac66b4e5 Merge PR #5438 from rodboev: add preset cron schedule builder (#5427) 2026-07-03 22:16:37 +00:00
nesquena-hermes 8269de961e fix(test): stub _cancelThrottledSnapshotTimer + _clearAnchorProseIncrementalNode in #5224 node harness
The #5466 fix added these two cleanup calls to _restoreSettledSession; the
test_issue5224 node harness extracts+runs that function with every helper
stubbed on globalThis, but hadn't stubbed the two new ones — so the calls threw,
the function's catch returned 'error' instead of 'restored', failing 8 CI shards.
Add the stubs. (Local full-suite missed it on first run; CI sharding surfaced it.)
2026-07-03 22:04:54 +00:00
nesquena-hermes f3bf04c69a docs(changelog): #5466 incremental live streaming render (O(n^2)->O(n)) (#5455) 2026-07-03 21:44:10 +00:00
nesquena-hermes eaf7d1e9ab gate-fix #5466: stamp anchor attrs on incremental node + teardown on all terminal paths
Codex gate findings (2 SILENT, both fixed):
- ui.js: incremental prose node now flows through the shared row-decoration
  block (data-anchor-scene-row/-row-id/-row-role/-source-event-type) instead of
  returning early, so live incremental rows keep the identity attrs the scene
  reconciler matches on.
- messages.js: _cancelThrottledSnapshotTimer() + _clearAnchorProseIncrementalNode()
  now run on apperror, cancel, _handleStreamError, and _restoreSettledSession
  terminal paths (previously only fallback/done/stream_end) — closes the
  snapshot-timer/anchor-cache/window-global teardown gap.
- test: extend test_messages_js_stream_perf_cleanup_lifecycle to pin teardown on
  all four additional terminal paths.

CORE equivalence (Codex flagged smd != renderMd): reconciled — Opus's 1498-frame
harness against real smd.min.js proves incremental-smd == whole-smd byte-identical;
live-smd-vs-renderMd difference is the already-shipped fidelity model (main live
body streams smd, settles renderMd), and the incremental path is gated on !settled
so settled DOM still comes from renderMd. Not a regression.
2026-07-03 21:24:08 +00:00
nesquena-hermes 819f1a1e7b Merge PR #5466 from ai-ag2026: reduce O(n^2) streaming render to O(n) (#5455) 2026-07-03 21:04:16 +00:00
nesquena-hermesandruizanthony 5e5b44e733 fix(webui): replace cross-profile empty sessions on profile switch + open all-profile rows under owning profile
Clean rebase of ruizanthony's #5460 (rebase-first).

Co-authored-by: ruizanthony <ruizanthony@users.noreply.github.com>
2026-07-03 20:49:51 +00:00
nesquena-hermes 8fe2d63ec0 Merge remote-tracking branch 'origin/master' into release/stage-p1c
# Conflicts:
#	CHANGELOG.md
2026-07-03 20:44:31 +00:00
nesquena-hermes bc0a3b299a docs(changelog): note hidden-tab attention-chime timing delta (Opus advisor) 2026-07-03 20:43:42 +00:00
nesquena-hermes 2fd2d0951f docs(changelog): Batch C — #5464 read-only session-listing projection + #5465 pause hidden-tab polling (#5455) 2026-07-03 20:32:58 +00:00
nesquena-hermesandrumotoshino 5ea8b09b83 fix: prefer IPv4 for extension gallery downloads to prevent timeout on broken IPv6
Clean rebase of rumotoshino's #5458 (rebase-first).

Co-authored-by: rumotoshino <rumotoshino@users.noreply.github.com>
2026-07-03 20:26:18 +00:00
nesquena-hermes 6edcf14bbc Merge PR #5465 from ai-ag2026: pause background session polling while tab hidden (#5455) 2026-07-03 20:16:35 +00:00
nesquena-hermes 797eb4a1b9 Merge PR #5464 from ai-ag2026: open session-listing projection read-only (#5455) 2026-07-03 20:16:35 +00:00
nesquena-hermes eb59ac8fb3 docs(changelog): #5442 persist TTS/voice preferences server-side (#5435) 2026-07-03 20:14:49 +00:00
nesquena-hermes 8120e69e1d Merge PR #5442 from rodboev: persist TTS and voice preferences server-side (#5435) 2026-07-03 20:04:55 +00:00
nesquena-hermes fb6606152a docs(changelog): Batch A — #5453 profile overflow-model validation + #5449 read-only fork guard 2026-07-03 19:56:48 +00:00
nesquena-hermes a1f75a40c9 fix(test): assert branch-guard on the extracted helper, not stale inline text
test_branch_endpoint_consults_foreign_session_guard_on_missing_sidecar
grepped the inline handler block for _claim_or_synthesize_cli_session +
not_claimable + 403 — but #5449 extracted that logic into the
_load_branch_source_or_refuse helper, leaving only a dead comment carrying
the old text to satisfy the grep. Point the test at the helper so it asserts
real post-refactor structure instead of a comment.
2026-07-03 19:46:56 +00:00
nesquena-hermes f2ab07757f ship-pass: #5453 overflow-path regression test + drop #5449 dead comment
- Add test_profile_model_selection_accepts_model_in_overflow_extra_models
  (the extra_models overflow-bucket regression test the warm dossier flagged
  as the #5453 ship-pass note).
- Drop the stray dead pseudo-code comment left in handle_post branch route
  (#5449 cosmetic nit).
2026-07-03 19:45:37 +00:00
nesquena-hermes 00e7203ec8 Merge PR #5449 from rodboev: hide read-only cron fork affordances (#5439) 2026-07-03 19:44:33 +00:00
nesquena-hermes fa4b404542 Merge PR #5453 from WallaceWebster: include extra_models in profile model validation (#5453) 2026-07-03 19:44:33 +00:00
nesquena-hermesandallenliang2022 15fbcb4ce0 fix(chat): recover viewport anchor via sessionIdx when content-derived key goes stale
Clean rebase of allenliang2022's #5469 (rebase-first).

Co-authored-by: allenliang2022 <allenliang2022@users.noreply.github.com>
2026-07-03 19:44:32 +00:00
nesquena-hermes 0a80aa2296 docs(changelog): #5454 remove transparent-stream live-row entrance animation (residual #5367) 2026-07-03 18:31:13 +00:00
nesquena-hermesandRod Boev a085f919f2 Merge PR #5454 from rodboev: suppress transparent stream live row entrance animation (residual #5367)
Removes the #liveAssistantTurn .transparent-event-row entrance animation
rule and its now-unused @keyframes transparent-event-enter, eliminating the
entrance-animation replay on streaming rebuilds that remained after the
#5400 identity-reconcile fix. Depth-fade [data-transparent-fade] rules
preserved (avoids the #5406 opacity-clobber). Follow-up to already-closed #5367.

Co-authored-by: Rod Boev <rodboev@users.noreply.github.com>
2026-07-03 18:28:52 +00:00
nesquena-hermesandWallaceWebster 654daf8f2a fix(profiles): include extra_models in profile model validation
Clean rebase of WallaceWebster's #5453 (rebase-first).

Co-authored-by: WallaceWebster <WallaceWebster@users.noreply.github.com>
2026-07-03 03:26:25 +00:00
nesquena-hermesandrodboev 0735a1b853 fix(#5439): hide read-only cron fork affordances
Clean rebase of rodboev's #5449 (rebase-first).

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-03 00:58:30 +00:00
nesquena-hermes a6504a8c58 fix(#5434): scope new Mermaid sizing to inline only — restore master lightbox behavior + inline Fit button (Codex gate findings)
Codex re-gate found 2 SILENT regressions the certifier missed:
- inline lost the 'Fit to screen' toolbar button (PR gated Fit to lightbox-only)
- the new readable-scale/envelope path leaked into lightbox mode (changed zoom-out floor + fit init for wide diagrams)
Fix: toolbar restored to master shape (Fit for all modes, Fullscreen inline-only);
_minScale() returns the flat _MERMAID_VIEWER_MIN_SCALE for lightbox; lightbox init
restored to master's _fitScale()/box*initialFit; the new readable-height sizing is
now scoped strictly to inline mode. Tests updated to the master-consistent contract.
2026-07-02 22:37:12 +00:00
nesquena-hermes 9f7d7e986b docs(changelog): #5434 inline Mermaid sizing 2026-07-02 22:23:23 +00:00
nesquena-hermes cb8ab640b5 Merge #5434: restore readable inline Mermaid sizing (#5413) [rodboev] 2026-07-02 22:22:27 +00:00
nesquena-hermesandrodboev a4ad03bd68 fix(#5413): restore readable Mermaid sizing (rebased onto current master w/ #5437)
Clean rebase of rodboev's #5434 (rebase-first, re-based post-#5437).

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-02 21:56:29 +00:00
nesquena-hermes 5ca3bc7f3d docs(changelog): #5437 harden ElevenLabs TTS transport (no-redirect/no-proxy opener) 2026-07-02 21:36:08 +00:00
nesquena-hermes 2dcf7f529e Merge #5437: harden ElevenLabs TTS transport guards (#5430) [rodboev] 2026-07-02 21:35:42 +00:00
nesquena-hermes f7338f32dd docs(changelog): #5441 cap update summary sessionStorage cache at 256KB 2026-07-02 21:14:32 +00:00
nesquena-hermes dc7e9e34d2 Merge #5441: cap generated update summary cache (#5435) [rodboev] 2026-07-02 21:14:03 +00:00
nesquena-hermesandrodboev e65013676a fix(#5435): cap generated update summary cache
Clean rebase of rodboev's #5441 (rebase-first).

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-02 20:46:33 +00:00
nesquena-hermes 01487009d6 fix(#5408): add missing German providers_status_model locale key; correct CHANGELOG to note Test-connection reuses the authenticated onboarding probe (Codex gate findings) 2026-07-02 20:37:15 +00:00
nesquena-hermes 2c0ab5ef94 docs(changelog): #5408 self-hosted provider setup (Ollama/LM Studio) in Settings 2026-07-02 20:22:37 +00:00
nesquena-hermes 8689c40995 Merge #5408: self-hosted provider setup (Ollama/LM Studio) in Settings (#3260) [rodboev] 2026-07-02 20:20:12 +00:00
nesquena-hermes 4e57aed491 docs(changelog): #5404 hide inactive prompt flyouts from screen readers 2026-07-02 19:52:48 +00:00
nesquena-hermes 517419f18a Merge #5404: hide inactive prompt flyouts from screen readers [sheldon-im] 2026-07-02 19:52:19 +00:00
nesquena-hermes 75891eac90 docs(changelog): #5392 mobile overflow-anchor defer (residual #4856 jump-back) 2026-07-02 19:36:18 +00:00
nesquena-hermes 2839c16ab7 Merge #5392: defer mobile overflow-anchor suppression across height-churn window (#4856) [allenliang2022] 2026-07-02 19:35:40 +00:00
nesquena-hermes 82dbb8d35e docs(changelog): #5402 sidebar action menu stays open on chat scroll 2026-07-02 19:10:40 +00:00
nesquena-hermes 76f31a5478 Merge #5402: keep sidebar action menu open during chat scroll (#5347) [nankingjing] 2026-07-02 19:10:24 +00:00
nesquena-hermes 5fe110afd5 docs(changelog): #5400 transparent-stream live-row reconcile 2026-07-02 18:44:52 +00:00
nesquena-hermes 3763f60646 Merge #5400: preserve transparent stream live rows on rerender (#5367) [rodboev] 2026-07-02 18:44:30 +00:00
nesquena-hermes 176720b55a fix(profiles): guard non-string cached model in dropdown render + purge from cache predicate (Codex gate finding on #5412)
A poisoned cache row {name:'x', model:{}} passed the name-only cache predicate
but threw 'p.model.split is not a function' synchronously on profile-chip click,
bricking profile switching until localStorage was cleared. Guard both render
sites (typeof p.model==='string') and reject unsafe model types in
_profileDropdownDataCacheUsable; regression covers {model:{}} and {model:123}.
2026-07-02 18:27:27 +00:00
nesquena-hermes cd5cb02635 docs(changelog): #5412 instant profile-dropdown open 2026-07-02 18:20:18 +00:00
nesquena-hermes b5bd4465b6 Merge #5412: speed up profile dropdown opening [ruizanthony] 2026-07-02 18:19:57 +00:00
nesquena-hermes bf1ca227dd fix(tts): block non-globally-routable addrs (CGNAT/Tailscale 100.64.0.0/10) via not-is_global backstop + tests (Opus follow-up on #5407) 2026-07-02 18:04:28 +00:00
nesquena-hermes 15dc671c0a docs(changelog): #5407 TTS DNS-rebind SSRF hardening 2026-07-02 17:45:49 +00:00
nesquena-hermes 24eb618571 Merge #5407: pin OpenAI TTS proxy connect target vs DNS-rebind TOCTOU (#5291) [rodboev] 2026-07-02 17:45:04 +00:00
nesquena-hermes 27df663246 docs(changelog): #5423 profile-switch new-session 404 + #5424 health Bearer auth 2026-07-02 17:08:16 +00:00
nesquena-hermes b184588e8a Merge #5424: Bearer auth on remote /health/detailed probe (#5418) [nankingjing] 2026-07-02 17:07:51 +00:00
nesquena-hermes 2f353e7a16 Merge #5423: unblock session/new after profile switch (#5420) [nankingjing] 2026-07-02 17:07:51 +00:00
nesquena-hermesandnankingjing 32baf1302b fix(routes): unblock session/new after profile switch (#5420)
Clean rebase of nankingjing's #5423 (rebase-first).

Co-authored-by: nankingjing <nankingjing@users.noreply.github.com>
2026-07-02 16:34:37 +00:00
nesquena-hermesandnankingjing 4d7fad06e6 fix(health): send Bearer auth on remote /health/detailed probe (#5418)
Clean rebase of nankingjing's #5424 (rebase-first).

Co-authored-by: nankingjing <nankingjing@users.noreply.github.com>
2026-07-02 16:24:39 +00:00
nesquena-hermesandrodboev 4e74de45f8 fix(#5367): preserve transparent stream live rows on rerender (rehydrate controls)
Clean rebase of rodboev's #5400 (rebase-first).

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-02 14:49:05 +00:00
nesquena-hermesandrodboev 56889fa35e fix(#5291): pin OpenAI TTS proxy + iterate vetted RRset (DNS-rebind TOCTOU)
Clean rebase of rodboev's #5407 (rebase-first).

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-02 14:38:09 +00:00
nesquena-hermesandruizanthony 2032ac079e fix: speed up profile dropdown opening (preserve shared single-profile cache)
Clean rebase of ruizanthony's #5412 (rebase-first).

Co-authored-by: ruizanthony <ruizanthony@users.noreply.github.com>
2026-07-02 13:38:43 +00:00
nesquena-hermesandnankingjing 791523dffa fix(ux): keep sidebar action menu open during chat scroll + close on anchor detach (#5347)
Clean rebase of nankingjing's #5402 (rebase-first).

Co-authored-by: nankingjing <nankingjing@users.noreply.github.com>
2026-07-02 10:09:55 +00:00
nesquena-hermesandrodboev 7220747a1d feat(#3260): self-hosted provider setup (Ollama/LM Studio) in Settings (i18n complete)
Clean rebase of rodboev's #5408 (rebase-first).

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-02 08:17:44 +00:00
nesquena-hermesandsheldon-im 012c66d12c Hide inactive flyouts from screen readers (+ visual-hide CSS)
Clean rebase of sheldon-im's #5404 (rebase-first).

Co-authored-by: sheldon-im <sheldon-im@users.noreply.github.com>
2026-07-02 07:15:53 +00:00
nesquena-hermes 9714122c98 chore(changelog): #5162 default message mode rename + steer default 2026-07-02 05:45:54 +00:00
nesquena-hermesandRod Boev b931ae2f9b fix(settings): reconcile #5145 rename+steer-flip onto master's #5170 mirror
Rebase PR #5162 (rename busy_input_mode -> default_message_mode; flip the
default from 'queue' to 'steer') onto current origin/master WITHOUT dropping
the shipped #5170 localStorage persistence mirror.

Rename the mirror machinery to the new setting name for consistency:
  _BUSY_INPUT_MODES        -> _DEFAULT_MESSAGE_MODES        (values unchanged)
  _normalizeBusyInputMode  -> _normalizeDefaultMessageMode  (fallback now 'steer')
  _persistBusyInputMode    -> _persistDefaultMessageMode
  _readPersistedBusyInputMode -> _readPersistedDefaultMessageMode
  window._busyInputMode    -> window._defaultMessageMode (+ renamed exports)

localStorage: write the new 'hermes-default-message-mode' key; read it with a
fallback to the legacy 'hermes-busy-input-mode' key so an existing user's
persisted preference survives the rename.

Preserve #5170 behavior at every mirror site under the new names:
  - boot success  -> window._defaultMessageMode=_persistDefaultMessageMode(...)
  - boot FAILURE  -> window._defaultMessageMode=_readPersistedDefaultMessageMode()
    (NOT a hardcoded 'steer' — a saved 'interrupt'/'queue' must still apply when
    the server is unreachable; do not regress #5167/#5132)
  - preferences autosave, settings-panel load, and _applySavedSettingsUi all
    persist through _persistDefaultMessageMode(...)

Tests updated for the rename while keeping the persistence-behavior assertions
(test_1062, test_5145, test_5167); test_5167 gains explicit guards that the
load-failure path reads the persisted pref and never hardcodes a literal mode,
plus autosave/panel-load mirror-write coverage.

Co-authored-by: Rod Boev <rod.boev@gmail.com>
2026-07-02 05:44:48 +00:00
nesquena-hermes 404585a831 chore(changelog): #5399 session-list 502 retry + #5209 update-summary expand 2026-07-02 05:23:01 +00:00
nesquena-hermesandweidzhou 3fde698232 fix(sessions): always retry sidebar session-list GET on 502/503/504 (#5394)
The sidebar session-list GET had 502/503/504 retry logic, but it was gated
to cold boot only. Once `_sessionListHasLoadedOnce` flipped true, every later
refresh (profile switch, focus/visible/reconnect) shipped no retryStatuses, so
a transient 502 during an nginx->backend restart window failed on the first
attempt and left the sidebar stale until a hard reload (Ctrl+F5).

The session-list GET is idempotent, so retrying it is safe unconditionally.
This moves `retries:1` + `retryStatuses:[502,503,504]` into the base request
options so they apply to every refresh, while keeping the larger boot timeout
(`_SESSION_LIST_BOOT_TIMEOUT_MS`) and `retryTimeouts` boot-only. The api()
wrapper in static/workspace.js already retries when the error status is in
retryStatuses, so no other change is needed.

Extends the existing source-string regression test to assert the retry
options are now always present (declared before the boot-only gate) while the
boot path still carries the timeout + timeout retry.

Reported and root-caused by @weidzhou, who traced the boot-only retry gate.

Co-authored-by: weidzhou <weidzhou@users.noreply.github.com>
2026-07-02 05:13:59 +00:00
nesquena-hermes da33f1e3d8 chore(changelog): #5398 stop auto-creating Cron Jobs project without opt-in 2026-07-02 04:37:11 +00:00
nesquena-hermesandallenliang2022 9fd349898f fix(chat): defer mobile overflow-anchor suppression (re-arm reachable + independent hard cap) #4856
Clean rebase of allenliang2022's #5392 (rebase-first).

Co-authored-by: allenliang2022 <allenliang2022@users.noreply.github.com>
2026-07-02 04:01:38 +00:00
nesquena-hermes 21f321c06c test: update read-only action-menu shape assertion for the appended Export item 2026-07-02 03:34:36 +00:00
nesquena-hermes f50b1d84e1 feat(sessions): move Export-to-HTML into the sidebar conversation menu
Follow-up to v0.51.819 which removed the export button from the composer footer
(it tripped the footer overflow-collapse, hiding model/workspace labels). Per
design consult (Fable) + ChatGPT/Open-WebUI convention, export now lives in the
per-conversation sidebar three-dot action menu, right after Duplicate:
- exportSessionHTML(session) parameterized (was active-session-only); Settings
  button now wired ()=>exportSessionHTML() and still exports the active session
- new _appendSessionExportHtmlAction() added after Duplicate + in the read-only
  early-return branch (export is non-mutating; imported sessions re-exportable)
- exports THAT row's conversation, not just the active one
- download icon added to ICONS; session_export_html[_desc] added to 14 locales
- Settings HTML button retained as secondary data-management entry
2026-07-02 03:21:18 +00:00
nesquena-hermes efe72238bc chore(changelog): composer-footer export-button removal hotfix 2026-07-02 02:51:42 +00:00
nesquena-hermes 219615b5a7 fix(composer): remove Export-to-HTML button from composer footer (keep settings-panel export)
The #4968 export button was hard-inserted into the composer footer .composer-left
row, bypassing the configurable composer-control framework. On desktop it pushed the
footer over its overflow threshold, tripping _fitComposerFooter into cf-icons mode
which HIDES the model/workspace/profile text labels. Removing it restores label
visibility. Export stays available via the settings-panel HTML button (#btnExportHTML).
2026-07-02 02:48:45 +00:00
nesquena-hermes a28b991ce3 chore(changelog): #4968 export chat to themed HTML 2026-07-02 02:38:01 +00:00
nesquena-hermes b31f3fab3b #4968: export chat to self-contained themed HTML, rebased on master 2026-07-02 02:36:09 +00:00
nesquena-hermes a7618555ac chore(changelog): #5390 blank assistant turn fix 2026-07-02 02:25:18 +00:00