Release: decode JSON-array-string skills.disabled in Skills panel (#7120, @webtecnica) (#7141)

Co-authored-by: n <a@n>
This commit is contained in:
nesquena-hermesandn authored and GitHub committed 2026-08-19 02:41:38 +00:00
1 parent 20123b1268
commit bec67d60ea
1 file changed
+1
+1
View File
@@ -5,6 +5,7 @@
### Fixed
- **The Skills panel no longer shows every skill as enabled (and silently drop your other disabled skills on a toggle) when `skills.disabled` is stored as a JSON-array string.** `hermes config set skills.disabled …` and JSON-mode config saves persist the list as a quoted string (`'["skill-a","skill-b"]'` or the Python-literal `"['a']"`), which the panel read as a single literal skill name — so no skill matched, all rendered enabled, and toggling one rewrote `skills.disabled` to a one-entry list, discarding the rest. The panel read and the toggle write now decode the JSON-array/Python-literal string form into a real list (reusing the agent's shared parser when present so the two surfaces cannot drift, with a safe `ast.literal_eval` fallback), while a genuine scalar skill name still means one entry. Thanks @webtecnica. (#7120)
- **Loading several large sessions at once can no longer spike memory into an out-of-memory crash.** Full sidecar resolution (the expensive JSON parse for a large transcript) is now bounded by a small semaphore, and concurrent requests for the same session elect a single leader that parses once while the others wait for its cached result instead of each parsing their own copy — so a burst of tabs or reconnects against big sessions can't multiply transient memory. Metadata-only reads and cache hits stay on the lock-free fast path, and a failed parse always releases its slot (no capacity leak). Thanks @Dandandad. (#7127)
- **Reconnecting to a live chat stream now resumes from the client's last received event instead of losing the tail or replaying the whole turn.** The `/api/chat/stream` endpoint honors the SSE `Last-Event-ID` header (and `after_event_id` / `after_seq` / `replay=1`) with a resume cursor that carries provenance, so a dropped connection re-subscribes at the right place: an in-range cursor replays only the gap, an unparseable/foreign/ahead cursor fails closed to replay-from-start (never silently skipping frames), and a genuinely truncated buffer still emits `recovery_control`. A prior edge where an ahead cursor with no known snapshot cutoff installed itself as the live dedup bound — discarding every queued frame including the terminal `stream_end` and stalling the reconnect on heartbeats — is fixed by treating an unknown cutoff as fence 0 before normalization. Thanks @Paladin173. (#6886)
- **A parked no-run approval can no longer mask the real pending approval when a gateway producer is live.** No-run "legacy" approval mirrors are now stamped with a token derived from their own live producer, and whenever a session's gateway queue has live producers the reconciler tokenizes from the authoritative head and discards any unmatched or tokenless mirror instead of letting it linger — so a stale card can't sit in front of the genuine pending approval (previously gateway mode returned 409 and permanently retained the stale mirror, and local mode reported success while resolving nothing). Tokenless-orphan retention is preserved for the no-producer case, and responding to a stale id fails without waking a different producer. Thanks @VHSgunzo. (#7086)