Commit graph

7285 commits

Author SHA1 Message Date
nesquena-hermes
7a862c9f6d
Merge pull request #6115 from nesquena/stage/css2-batch
Release exp: narrow-screen CSS fixes — popup min-width (#6104) + timestamp foldable layout (#6106)
2026-07-15 17:23:14 -07:00
nesquena-hermes
ee7ec5e5d7 Release exp batch: narrow-screen CSS fixes — approval/clarify popup min-width (#6104) + stream-timestamp foldable layout (#6106).
Scoped to the two stated fixes only: strips the #composerModelDropdown position:fixed
mobile override that #6104's branch had bundled in (that's the #6080 model-picker
mechanism, being reworked separately to reparent to body level — the fixed override
is trapped by .composer-footer's container-type so it doesn't belong here), and drops
the <=360px tool-name-hiding rules (header overflow-clip prevents the spill without
losing tool identity). Thanks @webtecnica.
2026-07-16 00:10:25 +00:00
nesquena-hermes
928646a57c Merge commit 'refs/pull/6106/head' of github.com:nesquena/hermes-webui into stage/css2-batch 2026-07-15 23:58:12 +00:00
nesquena-hermes
89e443674e Merge commit 'refs/pull/6104/head' of github.com:nesquena/hermes-webui into stage/css2-batch 2026-07-15 23:58:10 +00:00
nesquena-hermes
a155a616c7
Merge pull request #6111 from nesquena/stage/5913-pinchzoom
Release exp: pinch-to-zoom for Mermaid diagrams on touch devices (#5913)
2026-07-15 16:06:58 -07:00
nesquena-hermes
9c0e0986c3 Release exp: pinch-to-zoom for Mermaid diagrams on touch devices (#5913). Thanks @silent-reader-cn. 2026-07-15 23:02:13 +00:00
silent-reader-cn
0403f00789 fix: address Greptile review and fix CI test mock for touch handlers
Three fixes in one commit:

1. **CI test mock** — Added addEventListener/removeEventListener to the
   Node.js makeElement mock so viewport.addEventListener() calls in the
   touch handler registration don't crash with 'not a function'.

2. **Two-finger pan during pinch** — Replaced _setScale() call with
   direct transform math. The new formula computes scale and position
   simultaneously:
     ratio = boundedScale / pinchStartScale
     x = currMidX - (startMidX - startPosX) * ratio
   This keeps the diagram under both fingers regardless of midpoint
   drift, enabling simultaneous zoom + pan.

3. **Post-pinch click suppression** — _onTouchEnd now sets dragged=true
   when exiting pinch mode so any synthesized click event is caught
   by the existing dragged guard in _openViewerOnClick instead of
   opening the lightbox.
2026-07-15 23:02:13 +00:00
silent-reader-cn
7419b1bb51 feat: add pinch-to-zoom support for Mermaid diagrams on touch devices
Adds touch event handlers (touchstart/touchmove/touchend/touchcancel) to
the Mermaid viewer viewport for two-finger pinch zoom, using the existing
_setScale() function with midpoint anchoring.

- Guards pointer handlers (down/move/click) during active pinch to prevent
  interference between touch and pointer event systems
- Uses {passive: false} on touchstart/touchmove to allow preventDefault()
- Falls back gracefully on non-touch devices — touch listeners are inert
  without touch hardware

Fixes: Mermaid diagrams in Hermes WebUI were not zoomable via multi-touch
pinch on mobile/tablet devices, frustrating users with complex diagrams.
2026-07-15 23:02:13 +00:00
nesquena-hermes
a486c2f583
Merge pull request #6110 from nesquena/stage/6102-cachettl
Release exp: hold streaming CLI-cache TTL above sidebar poll cadence (#6102)
2026-07-15 15:55:24 -07:00
nesquena-hermes
a2d70b9e53 Release exp: hold streaming CLI-cache TTL above sidebar poll cadence (#6102). Thanks @starship-s. 2026-07-15 22:40:48 +00:00
nesquena-hermes
b877c9aa40 Merge commit 'refs/pull/6102/head' of github.com:nesquena/hermes-webui into stage/6102-cachettl 2026-07-15 22:40:21 +00:00
webtecnica
9ac68feecb fix: stream event timestamps layout on narrow foldable screens (#6099) 2026-07-15 18:31:51 -03:00
webtecnica
2143563109 fix: ensure approval/clarify popups have min-width on narrow screens (#6094) 2026-07-15 18:30:54 -03:00
nesquena-hermes
0f0f733b83
Merge pull request #6103 from nesquena/stage/6056-delegtitles
Release exp: delegated subagent sidebar titles (#6056) + sidebar title-redaction hardening
2026-07-15 14:20:17 -07:00
nesquena-hermes
38119fac25 fix(#6056): extend sidebar title-field redaction to /api/sessions/search (Codex class-fix)
Codex re-gate found the same derived-title leak on the sibling /api/sessions/search
endpoint (3 branches redacted only 'title'). Extract _redact_sidebar_title_fields()
shared helper, apply it in both _sidebar_session_response_item and all 3 search
branches, read api_redact_enabled once per search response (mirrors #4662). +helper
test + source-guard that every search branch calls the redactor.
2026-07-15 21:06:36 +00:00
starship-s
f5ef3688c6 fix(cache): keep streaming TTLs above poll cadence 2026-07-15 20:59:59 +00:00
nesquena-hermes
ffbc91343a fix(#6056): redact display_title/_state_db_title/parent_title on the sidebar API
Codex gate found the #6056 derived display_title (from raw user-message content)
bypassed sidebar redaction — the serializer redacted only 'title', so a credential
in a delegated goal leaked to the sidebar even with api_redact_enabled=True.
Redact display_title + _state_db_title + parent_title on the same path; +regression
test (proven to fail on the unfixed serializer).
2026-07-15 20:57:31 +00:00
nesquena-hermes
80cb79c7f7 Release exp: show delegated goal titles for generic subagent child sessions (#6056). Thanks @rodboev. 2026-07-15 20:47:11 +00:00
nesquena-hermes
b96405ef29 Merge commit 'refs/pull/6056/head' of github.com:nesquena/hermes-webui into stage/6056-delegtitles 2026-07-15 20:46:34 +00:00
nesquena-hermes
93a9bdcc3f
Merge pull request #6101 from nesquena/stage/6062-readrange
Release exp: show requested line range in collapsed read_file tool labels (#6062)
2026-07-15 13:41:13 -07:00
nesquena-hermes
6efbf899c9 Release exp: show requested line range in collapsed read_file tool labels (#6062). Thanks @franksong2702. 2026-07-15 20:37:32 +00:00
Frank Song
59c8f988ef fix(ui): reject invalid read range limits 2026-07-15 20:37:02 +00:00
Frank Song
5b46c54c92 feat(ui): show read ranges in collapsed tool labels 2026-07-15 20:37:02 +00:00
nesquena-hermes
3c9304aef5
Merge pull request #6098 from nesquena/stage/6088-manualupd
Release exp: allow manual update check when auto-update is disabled (#6088)
2026-07-15 13:20:26 -07:00
nesquena-hermes
2e93d04a57 Release exp: allow manual update check when auto-update is disabled (#6088) + regression test. Thanks @webtecnica. 2026-07-15 20:02:35 +00:00
nesquena-hermes
754dcca048 Merge commit 'refs/pull/6088/head' of github.com:nesquena/hermes-webui into stage/6088-manualupd 2026-07-15 20:02:02 +00:00
nesquena-hermes
ad88366baa
Merge pull request #6097 from nesquena/stage/6081-noresp
Release exp: suppress false no-response after tool-limit turn with a final answer (#6081)
2026-07-15 12:43:22 -07:00
nesquena-hermes
e41507d164 Release exp: suppress false no-response after tool-limit turn with a final answer (#6081). Thanks @coyaSONG. 2026-07-15 19:39:02 +00:00
chsong
139c76535b fix tool-limit final answer classification 2026-07-15 19:38:25 +00:00
nesquena-hermes
57e8aafb16
Merge pull request #6096 from nesquena/stage/6083-brick
Release exp: fix new-conversations-unstartable brick + eviction leak bound (#6083)
2026-07-15 12:21:19 -07:00
nesquena-hermes
30059085c2 fix(#6083): only grace-evict CONFIRMED never-persisted shells (Codex finding #2)
Codex re-gate asked to distinguish a confirmed-absent sidecar from an
indeterminate/unreadable one before entering the abandoned-shell grace path.
Add _session_sidecar_exists() (True/False/None) and only grace-evict when the
sidecar is confirmed absent (False); a present-or-indeterminate sidecar keeps
the session resident. Age-window bound retained (fully closes the leak, no
data-loss edge); an SSE-mounted-lease refinement is noted as optional follow-up.
2026-07-15 19:06:10 +00:00
nesquena-hermes
02e5acb890 fix(#6083 follow-up): bound never-persisted empty session shells
Codex gate found the eviction-reorder made never-saved empty shells immortal
(abandoned /api/session/new tabs accumulate unbounded past sessions_cache_max).
Add a grace-window bound: protect a never-persisted empty shell only while fresh
(<30min old) OR while it carries a composer draft; a stale, empty, draftless,
never-saved shell is treated as abandoned and becomes evictable again. A real
compose persists a draft on the first keystroke (disk-backed + reloadable), so
the brick fix is preserved while the leak is closed. +2 regression tests.
2026-07-15 18:44:21 +00:00
nesquena-hermes
0881b8ec0c Release exp: fix new-conversations-unstartable (password-manager autofill evicts unsaved session) (#6083). Thanks @ai-ag2026. 2026-07-15 18:24:11 +00:00
nesquena-hermes
078a64cabe Merge commit 'refs/pull/6083/head' of github.com:nesquena/hermes-webui into stage/6083-brick 2026-07-15 18:23:03 +00:00
webtecnica
40d5e17006 fix: allow manual force-check even when auto-update is disabled (#6082) 2026-07-15 12:18:04 -03:00
ai-ag2026
b6733ccf6e fix(webui): give the onboarding password inputs a form owner too
Completes the previous commit. It gave the Settings password fields an explicit
<form>, but onboarding.js injects two more password inputs (API key, password)
with no form owner. While the wizard is mounted the document is back to having
unowned password fields — exactly the shape that makes Chromium synthesise one
document-wide credential form and autofill the saved account name into the
sidebar conversation filter.

Same treatment: a display:contents <form> wrapper (no layout impact) plus
autocomplete tokens. All five password inputs in the app are now form-owned, so
there is no unowned credential form left for Chromium to build from.

Verified no CSS depends on .onboarding-field / .onboarding-copy being children
or siblings of the wrapped nodes, and no JS traverses their parents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 10:41:16 +02:00
ai-ag2026
7707ea1d2a fix(webui): stop password managers autofilling the search box, and keep unsaved sessions startable
Two independent defects that chain into "new conversations cannot be started":
every POST /api/session/draft and /api/chat/start 404s a few seconds after
POST /api/session/new returned 200.

1. Search inputs are parsed as username fields.

index.html contains no <form> at all, but does contain password inputs (the
Settings "Access Password" panel). Chromium therefore groups the document's
unowned fields into one synthetic password form and picks the first text input
in the DOM — #sessionSearch, the sidebar conversation filter — as that form's
username field, then autofills the saved account name into it on load.
autocomplete="off" was already present; it is ignored for credential
heuristics.

The autofill fires oninput -> filterSessions() -> GET /api/sessions/search
?content=1&depth=5: a full content search the user never asked for, repeated
on every page load.

Fix: give the four search inputs type="search" plus the per-manager opt-outs
(data-1p-ignore / data-lpignore / data-bwignore / data-form-type), and give the
Settings password inputs a real <form> owner with proper autocomplete tokens so
Chromium scopes the credential form to them instead of to the whole document.
The form uses display:contents, so layout is unchanged. CSS suppresses WebKit's
native search clear button, since these fields ship their own
(#sessionSearchClear).

2. A never-persisted session is treated as evictable.

new_session() intentionally keeps a session in RAM until its first message
(#1171), so the SESSIONS cache is its only copy. _session_is_evictable()
(#4765) short-circuited on zero messages, reasoning that an empty shell "is
recreated on next access". It is not: get_session() has no recreate path and
raises KeyError, so both routes 404 and the session can never be started.

The content search from (1) pulls every hit through get_session(), which blows
past sessions_cache_max (default 300) and evicts the session being composed.
That is why this reproduces within seconds on an install with ~1700 sessions,
and why it grew worse as the session count rose.

Fix: require proof of persistence before evicting, for empty sessions too —
which is what the function's own docstring already promised ("Its full state is
already persisted to the JSON sidecar"). The zero-message branch was the single
path that bypassed it. #4765's memory bound is unaffected: sessions loaded from
disk remain evictable, and its existing tests still pass.

Trade-off: an unsaved empty session now stays resident for the process
lifetime (one per "New Conversation" click, an empty object each). That is a
deliberate application of the function's stated invariant — "slightly more RAM
for a session we are unsure about is strictly better than evicting an unsaved
session". Bounding it by age instead would also work if maintainers prefer.

Validation:
  pytest tests/test_issue4765_sessions_lru_eviction.py  ->  9 passed
  The added regression test fails on the unpatched predicate (verified by
  reverting api/models.py alone) and passes with the fix.

Note: (1) fixes what triggers the churn, (2) fixes what turns that churn into
an unstartable session. Either fix alone leaves a real defect in place, so
they are submitted together.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 10:06:41 +02:00
nesquena-hermes
c677e4c71a
Merge pull request #6077 from nesquena/stage/6048
Release exp: preserve visible reasoning on deferred anchor paint (#6048)
2026-07-14 16:48:45 -07:00
nesquena-hermes
f803eb2fcf Release exp: preserve visible reasoning on deferred anchor paint (#6048). Thanks @franksong2702. 2026-07-14 23:44:11 +00:00
nesquena-hermes
4f5f197f9a Merge commit 'refs/pull/6048/head' of github.com:nesquena/hermes-webui into stage/6048 2026-07-14 23:43:22 +00:00
Frank Song
e13ebd96c1 fix(chat): align reasoning fallback identity key 2026-07-15 07:10:02 +08:00
Frank Song
e5c5fd63d4 test(chat): accept keyed reasoning fallback path 2026-07-15 06:58:02 +08:00
Frank Song
90e9f04dab fix(chat): key reasoning fallback to exact anchor row 2026-07-15 06:58:02 +08:00
Frank Song
a89a6be075 fix(chat): avoid duplicate reasoning fallback owner 2026-07-15 06:58:02 +08:00
Frank Song
e79f3cf53e fix(chat): recover reasoning after stale live turn 2026-07-15 06:58:02 +08:00
Frank Song
54f43b37fa fix(chat): isolate reasoning fallback by session 2026-07-15 06:58:02 +08:00
Frank Song
4f2190c500 fix(chat): preserve visible reasoning ownership 2026-07-15 06:58:02 +08:00
nesquena-hermes
7532e4a508
Merge pull request #6076 from nesquena/docs/change-guidelines
docs: change guidelines to reduce PR review rounds (GUIDELINES.md + AGENTS.md)
2026-07-14 15:49:38 -07:00
nesquena-hermes
13b640a219
Merge branch 'master' into docs/change-guidelines 2026-07-14 15:45:29 -07:00
nesquena-hermes
fd8539cc98
docs(changelog): stamp v0.52.41 stable section (promotion) (#6075)
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-07-14 15:42:25 -07:00