Commit graph

4637 commits

Author SHA1 Message Date
Rod Boev
0435dddda1 Move approval handler before tool.progress per GPT-5.5 spec review 2026-06-20 08:59:52 -04:00
Rod Boev
9bc84dcad5 Unify approval handler blocks and add debug logging per review 2026-06-20 08:48:55 -04:00
Rod Boev
39d18b39c7 fix: remove unused imports flagged by ruff 2026-06-20 08:40:44 -04:00
Rod Boev
f19b0ffc67 fix: relay approval SSE events on the legacy gateway chat/completions path 2026-06-20 08:32:02 -04:00
nesquena-hermes
c1a24171e8
Merge pull request #4545 from nesquena/stage-4540
Release v0.51.537 — queued card clears on session switch (#4533)
2026-06-20 00:16:00 -07:00
nesquena-hermes
0a30790689 ci: re-trigger (shard 3.11/2 flake — shard-2 isolation run green locally) 2026-06-20 07:12:51 +00:00
nesquena-hermes
2f3abb00be stage #4540 + CHANGELOG 2026-06-20 07:12:51 +00:00
nesquena-hermes
3d91defb66
Merge pull request #4546 from nesquena/stage-4542
Release v0.51.536 — transparent-stream tool-call rows persist after settle (#4539)
2026-06-20 00:09:30 -07:00
nesquena-hermes
348381bda3 stage #4542 @696bf798 (incl perf: pre-scan burst IDs) + CHANGELOG 2026-06-20 06:56:34 +00:00
nesquena-hermes
5b96d28139
Merge pull request #4541 from nesquena/stage-4537
Release v0.51.535 — keep open model picker stable during stream sync (#4531)
2026-06-19 23:21:37 -07:00
nesquena-hermes
2b398bb2b1 stage #4537: keep open model picker stable during stream sync (#4531, head 92de7615 incl duplicate-rebuild fix) + v0.51.535 CHANGELOG 2026-06-20 06:10:04 +00:00
nesquena-hermes
9988f0a3f6
Merge pull request #4538 from nesquena/stage-4524b
Release v0.51.534 — clarify prompt no longer bricks the session on expiry (#4504)
2026-06-19 22:48:27 -07:00
nesquena-hermes
15fe6add30 stage #4524: clarify 409-terminal (id-guarded, loading-cleared) + SSE-notify on expiry (#4504) + v0.51.534 CHANGELOG 2026-06-20 05:36:56 +00:00
nesquena-hermes
3433c7d6a1
Merge pull request #4532 from nesquena/stage-3285
Release v0.51.533 — restart gateway from the agent-health alert (#3285)
2026-06-19 21:52:32 -07:00
nesquena-hermes
90505c0a8e stage #3285: gateway restart from agent-health alert (POST /api/health/restart) + v0.51.533 CHANGELOG 2026-06-20 04:40:49 +00:00
nesquena-hermes
07174e06b3
docs(changelog): correct v0.51.530 attribution to @MinhoJJang (#4522) (#4528)
PR #4522 (fix /api/profiles UnboundLocalError 500) was authored by
@MinhoJJang, not @TomBanksAU. The wrong handle was carried forward from
the immediately preceding release (v0.51.529 / #4518, which IS TomBanksAU).
Corrects the credit on the v0.51.530 entry only.

Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
2026-06-19 21:16:03 -07:00
nesquena-hermes
500a91a4d5
Merge pull request #4529 from nesquena/stage-4516
Release v0.51.532 — built-in personalities on non-default profiles (#4465/#4513)
2026-06-19 21:09:13 -07:00
nesquena-hermes
e1e2bbc7ef fix(config): order ghost-home guard after ambient short-circuit (#4516 Codex gate)
Codex SILENT finding: the new 'if not target.exists(): return {}' guard ran
BEFORE the ambient-resolver short-circuit, so a matching ambient profile home
whose directory does not physically exist (fresh install / monkeypatched cfg)
returned {} instead of deferring to get_config() — breaking in-memory overrides
and changing the default-profile missing-home path. Move the guard below the
ambient short-circuit; add a regression test (matching-but-nonexistent ambient
home still defers to get_config()).
2026-06-20 03:57:56 +00:00
nesquena-hermes
acd2c186ef stage #4516: apply config defaults to non-default profile reads (#4465 / #4513) + v0.51.532 CHANGELOG 2026-06-20 03:51:55 +00:00
nesquena-hermes
673b364c53
Merge pull request #4526 from nesquena/stage-4517
Release v0.51.531 — plugins panel active-provider badge (#4496)
2026-06-19 20:49:49 -07:00
nesquena-hermes
a60ba78298 stage #4517: plugins panel active-provider badge via is_active_provider (#4496) + v0.51.531 CHANGELOG 2026-06-20 03:35:44 +00:00
nesquena-hermes
163a805813
Merge pull request #4525 from nesquena/stage-4522
Release v0.51.530 — fix /api/profiles 500 (UnboundLocalError regression)
2026-06-19 20:32:19 -07:00
nesquena-hermes
51e2fce823 stage #4522: fix /api/profiles UnboundLocalError 500 (regression from v0.51.528) + v0.51.530 CHANGELOG 2026-06-20 03:18:33 +00:00
nesquena-hermes
897d3832dd
Merge pull request #4523 from nesquena/stage-4518
Release v0.51.529 — per-response jump button matches session jump pill (#2246)
2026-06-19 20:09:28 -07:00
nesquena-hermes
6592416b35 stage #4518: match per-response jump button to session jump pill (#2246) + v0.51.529 CHANGELOG 2026-06-20 02:07:44 +00:00
nesquena-hermes
0dddca5b6b
Merge pull request #4519 from nesquena/release-v0.51.528-4454
Release v0.51.528 — isolated HERMES_HOME single-profile mode (#2698)
2026-06-19 19:03:01 -07:00
nesquena-hermes
078fb99589 test(#2698): stub hermes_cli.profiles via sys.modules, not mock.patch (CI shard-2 fix)
CI failed on shard 2 across ALL python versions (deterministic, not a flake):
test_list_profiles_prefers_matching_isolated_default_home did
mock.patch('hermes_cli.profiles.list_profiles', ...), whose string target forces
a REAL import of hermes_cli — not installed on the WebUI CI path (bundled agent
absent) -> ModuleNotFoundError. Passed locally only because hermes_cli is
importable here. Per the never-import-agent/hermes_cli-in-a-WebUI-test rule:
inject a stub hermes_cli + hermes_cli.profiles into sys.modules so
list_profiles_api()'s internal
resolves to the stub at the WebUI boundary. Verified: all 24 tests pass with
hermes_cli import BLOCKED (CI simulation).
2026-06-20 01:47:22 +00:00
nesquena-hermes
7cd464efa6 test(#4449): isolate state-dir contract tests via subprocess (fix suite-ordering leak)
The reload-based state-dir tests (importlib.reload(api.config) with mutated env)
leaked recomputed STATE_DIR/SESSION_DIR globals + stale references into later
tests in the full sequential run -> 17 spurious failures in cancel/stream/
health/state-isolation suites (all green in isolation). Restoring env + reloading
couldn't fully undo it (fixture/monkeypatch teardown ordering + other modules
holding by-value STATE_DIR refs). Rewrite the 3 tests to import api.config in a
fresh SUBPROCESS under the target env and read STATE_DIR from stdout — truly
isolated, can't pollute the test process. Same assertions (HERMES_HOME-derived
default, unset->platform default w/ cross-check, STATE_DIR override precedence).
2026-06-20 01:22:26 +00:00
nesquena-hermes
4d4b11b43c test+docs(#4449): backward-compat state-dir tests + upgrade migration note (Opus gate)
Opus flagged a real upgrade gap on the #4449 state-dir contract folded into
#4454: a deployment that relocated HERMES_HOME to a non-default base WITHOUT
setting HERMES_WEBUI_STATE_DIR sees WebUI state move to $HERMES_HOME/webui on
upgrade (empty app at the new address). Add (1) README note documenting the
move + how to keep the old location, and (2) two backward-compat regression
tests pinning the invariants: HERMES_HOME-unset stays at the platform default
(normal installs don't relocate), and HERMES_WEBUI_STATE_DIR takes precedence.
2026-06-20 00:51:08 +00:00
nesquena-hermes
8b598ac133 changelog: stamp v0.51.528 (Release SM) for #2698 isolated HERMES_HOME mode 2026-06-20 00:49:06 +00:00
nesquena-hermes
0952fcc606 fix(routes): drop redundant local _is_isolated_profile_mode import (#4454 gate)
The /api/profiles handler re-imported _is_isolated_profile_mode locally inside
handle_get, which made the name function-local for the ENTIRE handle_get scope
-> the earlier use at the /api/projects branch (routes.py:8000) hit
UnboundLocalError (F823), failing 6 test shards + lint. It's already a
module-level re-export (routes.py:429), so the local re-import is redundant;
removing it lets every in-function use resolve to the module global. Also drop
an unused 'from pathlib import Path' in the new #4449 state-dir test.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-06-20 00:48:20 +00:00
Rod Boev
e77ca8dbac fix(#2698): keep the pinned home across isolated fallbacks 2026-06-20 00:48:20 +00:00
Rod Boev
c7375c60c4 fix(#2698): clamp isolated profile lookups to the pinned home 2026-06-20 00:48:20 +00:00
Rod Boev
41f2015a32 fix(#2698): close isolated profile escape hatches 2026-06-20 00:48:20 +00:00
Rod Boev
f086158c10 fix(#2698): keep isolated deployments on their own state and profile roots 2026-06-20 00:48:19 +00:00
Rod Boev
c00bfab9f5 fix(#2698): keep isolated default-named profiles pinned 2026-06-20 00:48:19 +00:00
Rod Boev
498a5e73e3 fix(#2698): pin isolated runtime home to configured profile 2026-06-20 00:48:19 +00:00
Rod Boev
8da03dbbad Use HERMES_HOME path directly for isolated profile home resolution 2026-06-20 00:48:19 +00:00
Rod Boev
d267646b9b Add switch_profile isolation guard tests 2026-06-20 00:48:19 +00:00
Rod Boev
0291af5f85 Derive isolated profile name from HERMES_HOME path, not process-level default 2026-06-20 00:48:19 +00:00
Rod Boev
a2ca2ff0c2 fix(profiles): snapshot HERMES_HOME at import time for isolation detection (#2698) 2026-06-20 00:48:19 +00:00
Rod Boev
a40ed2dbb8 fix(test): clear profile cache between tests to prevent cross-test leakage (#2698) 2026-06-20 00:48:19 +00:00
Rod Boev
35eced6f35 fix(profiles): broaden except clause and sanitize error in isolated mode (#2698) 2026-06-20 00:48:19 +00:00
Rod Boev
bf7208f19b fix(test): mock agent.skill_utils to fix CI import errors (#2698) 2026-06-20 00:48:19 +00:00
Rod Boev
94c3d2028a fix(tests): remove unused imports and variables (#2698) 2026-06-20 00:48:19 +00:00
Rod Boev
36dbe1a415 fix(profiles): return 403 for isolated-mode guards, fix fallback identity (#2698) 2026-06-20 00:48:19 +00:00
Rod Boev
963f7c3864 fix(profiles): honor isolated HERMES_HOME profile mode (#2698) 2026-06-20 00:48:19 +00:00
nesquena-hermes
99d5db35c5
Merge pull request #4515 from nesquena/fix-4416-notif-wasever-hidden
Release v0.51.527 — completion notifications survive a backgrounded tab (#4416)
2026-06-19 17:05:34 -07:00
nesquena-hermes
ca19574b75 fix(notifications): make hidden-tracker stream-owned + clear on terminal paths (#4416 Codex gate)
Codex SHIP-WITH-FIXES: non-done terminal paths (apperror/cancel/stream-error
finalize) didn't clear _STREAM_WAS_HIDDEN, so a stale wasHidden=true could be
inherited by a later same-sid reconnect -> spurious notification. Make each
entry stream-owned ({streamId, wasHidden}) so a stale entry from a prior stream
is never trusted (reconnect keeps state only when streamId matches; done reads
via the owned entry), and add _clearStreamHidden(activeSid, streamId) on the
apperror/cancel/finalize-fallback terminal paths (belt-and-suspenders).
2026-06-19 23:54:23 +00:00
nesquena-hermes
d473f6c5a6 fix(notifications): notify on completion if tab was hidden during the stream (#4416)
A background tab's SSE is throttled by Chromium, so the stream 'done' event
arrives late (after the user returns, document.hidden=false) and the
response-complete notification was suppressed by the live visibility check.
Track per-stream whether the tab was hidden at ANY point during the stream
(_STREAM_WAS_HIDDEN, set at attach, OR'd by one idempotent visibilitychange
listener, read+cleared at done) and pass forceHidden accordingly.
sendBrowserNotification bypasses ONLY the live visibility gate on forceHidden,
still honoring the user's notifications-enabled setting — so a watched stream
stays silent (matches Slack/Discord/Gmail/Claude) but a backgrounded one
notifies. Correct fix for the #4416 root cause; supersedes #4421's always-fire
approach (which would also fire when the tab was never hidden).

Co-authored-by: bergeouss <bergeouss@users.noreply.github.com>
2026-06-19 23:48:42 +00:00