Commit graph

7250 commits

Author SHA1 Message Date
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
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
nesquena-hermes
74fd7ed3e1 docs: add change guidelines (GUIDELINES.md) + wire into AGENTS.md and CONTRIBUTING.md
Distilled habits that get a PR merged in one review round instead of several:
four root causes + ten rules + show-your-work PR-description contract. Full doc
in docs/GUIDELINES.md, compressed 10-point form in AGENTS.md (agent entry point),
pointer added to CONTRIBUTING.md reading list.
2026-07-14 22:40:52 +00:00
nesquena-hermes
a81872abfd
Merge pull request #6073 from nesquena/stage/5926
Release exp: cascade delegated subagent deletion (#5926)
2026-07-14 12:15:04 -07:00
nesquena-hermes
0a85a842c6 Release exp: cascade delegated subagent sessions on parent deletion (#5926). Thanks @pxxD1998. 2026-07-14 19:10:25 +00:00
nesquena-hermes
b8605e5561 Merge branch 'rebase-5926' into stage/5926 2026-07-14 19:09:29 +00:00
pxxD1998
73b6c5d604 fix(sessions): cascade delegated subagents on parent deletion 2026-07-14 18:10:03 +08:00
nesquena-hermes
3f3fa9b69a
Merge pull request #6057 from nesquena/stage/6054
Release exp: fail-closed gateway-restart recovery for agent updates (#6054)
2026-07-14 02:05:08 -07:00
nesquena-hermes
132bd8b270 Release exp: fail-closed gateway-restart recovery for agent updates (#6054). Thanks @franksong2702. 2026-07-14 08:58:53 +00:00
nesquena-hermes
b49c93c443 Merge branch 'rebase-6054' into stage/6054 2026-07-14 08:57:38 +00:00
Frank Song
59e92461fc fix: fail closed on wrapped gateway pid helpers 2026-07-14 16:36:23 +08:00
Frank Song
d08116b4d2 fix: harden gateway restart recovery targeting 2026-07-14 16:01:56 +08:00
Frank Song
ba1a058f87 fix: fail closed on implicit gateway pid recovery 2026-07-14 15:25:36 +08:00
Frank Song
14adbb61a4 fix: pin agent update gateway restart profile 2026-07-14 14:46:00 +08:00
Frank Song
885e267213 fix: retry transient agent gateway restart failures 2026-07-14 14:13:19 +08:00
nesquena-hermes
83a2471990
Merge pull request #6053 from nesquena/stage/6014
Release exp: faster session reconciliation — short-circuit impossible prefix (#6014)
2026-07-13 23:02:10 -07:00
nesquena-hermes
ce81d8acfd Release exp: short-circuit impossible state-db prefix reconciliation (#6014). Thanks @Isla-Liu. 2026-07-14 05:57:38 +00:00
nesquena-hermes
93a1e41675 Merge branch 'rebase-6014' into stage/6014 2026-07-14 05:46:27 +00:00
Isla-Liu
2e8915baf8 perf(webui): skip impossible state-db prefix normalization 2026-07-14 05:38:34 +00:00
nesquena-hermes
9a67cc2f8e
Merge pull request #6052 from nesquena/stage/6029
Release exp: honor agent worktree config default (#6029)
2026-07-13 21:52:24 -07:00
nesquena-hermes
07da3af768 Release exp: honor agent worktree config default in new chats (#6029). Thanks @ayxuerui. 2026-07-14 04:44:19 +00:00
nesquena-hermes
58129b9e84 Merge branch 'rebase-6029' into stage/6029 2026-07-14 04:43:53 +00:00
Rui Xue
b2c7578653 fix(sessions): guard all auto-mint paths + strict config/body parsing (gate review)
Gate review follow-ups for the #6022 no-leak rule: every non-deliberate
newSession/session-new call site passes worktree:false; only deliberate
New Chat inherits the config default.

- Strict boolean config read: only YAML true enables the default;
  quoted strings/ints/lists/dicts/null fall to the safe no-worktree
  default instead of truthiness-coercing.
- Presence-based explicit detection: 'worktree' in body — an explicit
  worktree:null is an opt-out, never a fall-through to config.
- Guarded remaining auto-mint call sites with explicit worktree:false:
  profile switch (panels.js), promptWorkspacePath + switchToWorkspace
  blank-page binds (panels.js), promptNewFile + promptNewFolder
  (ui.js), terminal auto-session (commands.js).
- Tests: worktree:null vs config-true (factory must not be called),
  strict-boolean malformed-shape matrix, static regression gates for
  every auto-mint site + a bare-body sweep so future auto-mint paths
  can't silently omit the key; updated the cmdTerminal preflight
  assertion for the new call shape.
2026-07-14 04:35:06 +00:00
Rui Xue
5f638a1694 feat(sessions): honor the agent's worktree config default in /api/session/new
/api/session/new treated an absent 'worktree' key as false, so the
agent's config-level 'worktree: true' default was never consulted for
WebUI sessions even though the WebUI reuses the agent's own worktree
helper. Both callers should agree on same-agent/same-repo isolation.

Three-value model:
- body 'worktree' absent -> agent config default applies (profile-aware
  via get_config_for_profile_home, so a user with worktree:true in one
  profile but not another gets per-profile behavior)
- explicit true/false -> honored verbatim; explicit always wins

Non-git workspaces: a config-default request degrades to a plain
session and surfaces 'worktree_skipped' in the payload; an explicit
worktree:true keeps the hard 400.

Frontend (same change, load-bearing): newSession() forwards explicit
true/false and omits the key otherwise; the boot-time auto-bind
(_maybeBindFreshDefaultWorkspaceSession) and the onboarding session
send worktree:false explicitly so a config default can never mint a
worktree + branch from merely opening the UI. Deliberate 'New Chat'
sends nothing and inherits the default.

Tests: route matrix (config on/off x body absent/true/false), non-git
fallback vs explicit 400, explicit-false-beats-config-true, config
helper (ambient/named-profile/fail-soft), static UI assertions that
auto-bind and onboarding opt out and New Chat paths don't pin a value.

Fixes #6022
2026-07-14 04:35:06 +00:00
nesquena-hermes
f617b6bb00
Merge pull request #6050 from nesquena/stage/5806
Release exp: profile-concept help localization + example (#5806)
2026-07-13 21:08:54 -07:00
nesquena-hermes
c690c0a7d3 Release exp: #5806 profile-concept help localization + example (Binding row dropped per maintainer). Thanks @rodboev. 2026-07-14 04:05:14 +00:00
nesquena-hermes
1a637f8142 Merge branch 'rebase-5806' into stage/5806 2026-07-14 04:04:49 +00:00
nesquena-hermes
503a369d0c refine(#2147): drop confusing Binding row, keep localization + Example
Maintainer revision of #5806: the localization refactor (all profile-concept
help text now goes through t() so it's translatable via the documented
English fallback) is the core value, and the concrete Example row genuinely
clarifies how profiles + workspaces work together. The Binding row restated
the Together row + added scheduled-task edge-case trivia that muddied a concept
explainer, so it's dropped (row + its 2 i18n keys + its test).

Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
2026-07-14 04:04:39 +00:00
nesquena-hermes
5d97c18242 fix(#2147): correct two inaccurate help-copy claims
- workspace 'scopes file access' -> 'keeps chat, terminal, and file browsing
  pointed at that project' (terminal/agent tools can access outside the workspace).
- scheduled tasks 'run under the profile that created them' -> 'run under the
  profile selected on the task, or the WebUI server default when none selected'.

Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
2026-07-14 03:40:21 +00:00
Rod Boev
acc63090dd test(#2147): honor english fallback-owned profile concept copy 2026-07-14 03:33:00 +00:00
Rod Boev
d2843d94e7 fix(#2147): restore i18n fallback for profile concept copy 2026-07-14 03:33:00 +00:00
Rod Boev
2f95ae7dbb fix(#2147): use stable label keys instead of splitting translated prose 2026-07-14 03:33:00 +00:00
Rod Boev
453b9696e3 fix(#2147): add profile_concept keys to all locale blocks and update existing test 2026-07-14 03:33:00 +00:00
Rod Boev
e9b17b1a52 feat(#2147): localize profile concept help and add usage examples 2026-07-14 03:33:00 +00:00
nesquena-hermes
a766ca21f8
Merge pull request #6049 from nesquena/stage/nix-slash
Release exp: Nix flake/module (#5431) + composer-focus shortcut (#5795)
2026-07-13 18:33:04 -07:00
nesquena-hermes
ca9444292d Release exp: Nix flake/NixOS module (#5431) + composer-focus shortcut (#5795). Thanks @rodboev.
#5431 (#2422): optional Nix flake + NixOS systemd module. Codex SAFE — zero non-Nix
  impact (only guarded bootstrap.py fallback touches core), secure-by-default
  (loopback, 0700/0077, non-root, EnvironmentFile secrets), 100 tests.
#5795 (#5759): Cmd/Ctrl+/ focuses composer. Codex SAFE after maintainer fix
  (matched e.key==='/' not physical Slash code so QWERTZ Ctrl+- zoom isn't stolen
  + shifted-/ works); focus-only, guarded, no conflict, 4 tests.
2026-07-14 01:25:40 +00:00