Commit Graph
100 Commits
Author SHA1 Message Date
nesquena-hermes fdf7e5e429 Merge pull request #7807 from nesquena/stage/0924-h
release: #6895 custom-provider model prefix stripped before send
2026-09-24 06:35:56 -07:00
nesquena-hermes 0052266c5d Merge pull request #7806 from nesquena/stage/0924-g
release: #6565 gateway reset and tool children stay separate from the parent session
2026-09-24 06:18:24 -07:00
nesquena-hermes d1b3787573 Merge pull request #7805 from nesquena/stage/0924-f
Release exp-v0.52.371: bound hidden-tab session polling while preserving profile recovery (#7301)
2026-09-24 04:43:48 -07:00
nesquena-hermes 9bf585ae88 Merge pull request #7804 from nesquena/stage/0924-e
Release exp-v0.52.370: keep image-turn context out of user bubbles; Edit/Undo keeps removed image turns removed (#7754)
2026-09-24 04:20:29 -07:00
nesquena-hermes 0c3550f4a7 Merge pull request #7802 from nesquena/stage/0924-d
Release exp-v0.52.369: scope MCP status, inventory and /reload-mcp to the request profile (#7720)
2026-09-24 03:33:03 -07:00
nesquena-hermes 05602c96fd Merge pull request #7801 from nesquena/stage/0924-c
Release exp-v0.52.368: phone soft-keyboard Enter inserts a newline (#6746)
2026-09-24 01:27:20 -07:00
nesquena-hermes 2d1e6f812a Merge pull request #7800 from nesquena/stage/0924-b
release: exp-v0.52.367 (#7798 CLI-archived sessions stay archived)
2026-09-24 00:04:26 -07:00
nesquena-hermes 5bfe845fbc Merge pull request #7797 from nesquena/stage/0924-a
Release: bounded recovery reads (#7628), prompt notifications (#7493), per-instance settings file (#6433)
2026-09-23 21:31:34 -07:00
nesquena-hermes 3f4e27e2ac Merge pull request #7795 from nesquena/stage/7765-subagent-project
Release: #7765 subagent sessions show inside their parent's project (@carlotestor)
2026-09-23 15:05:17 -07:00
nesquena-hermes fc4b61c68d Merge pull request #7794 from nesquena/stage/7779-cron-provider-pin
Release: #7779 cron keeps its provider-only pin when the model picker is Default (@cushingw)
2026-09-23 14:53:45 -07:00
nesquena-hermes d2c889409c Merge pull request #7793 from nesquena/stage/7610-oob-writeback
Release: #7610 scrub consumed /steer OOB wrapper from the settled transcript (@webtecnica)
2026-09-23 14:43:07 -07:00
nesquena-hermes 49ae188275 Merge pull request #7791 from nesquena/stage/7578-save-count
Release: #7578 large-session save counts messages without a full parse (@rodrigogs)
2026-09-23 14:23:29 -07:00
nesquena-hermes b978bedfbc Merge pull request #7790 from nesquena/stage/7682-stale-cancel
Release: #7682 stale-cancel recovery no longer duplicates a saved turn (@happy5318)
2026-09-23 14:12:29 -07:00
nesquena-hermes b8bda9a99e Merge pull request #7787 from nesquena/stage/7767-runtime-model
Release: #7767 publish the observed runtime model over SSE (@happy5318)
2026-09-23 10:32:52 -07:00
nesquena-hermes 8a3418668f Merge pull request #7786 from nesquena/stage/7651-inflight-cursor
Release: #7651 new-turn reconnect no longer resumes from the previous turn's cursor (@happy5318)
2026-09-23 09:58:45 -07:00
nesquena-hermes a027a2c899 Merge pull request #7784 from nesquena/stage/7743-context-baseurl
Release: #7743 context-length keeps base_url for ownerless and underscore-named providers (@webtecnica)
2026-09-23 09:37:22 -07:00
nesquena-hermes df491ee1b6 Merge pull request #7783 from nesquena/stage/7774-vanished-owner
Release: #7774 vanished-session KeyError maps to the recovery skip path (@happy5318)
2026-09-23 09:24:07 -07:00
nesquena-hermes 2ba3e40210 Merge pull request #7775 from nesquena/stage/7760-lease-warnings
Release: #7760 session-lease waits surface as warnings (@franksong2702)
2026-09-23 06:34:33 -07:00
nesquena-hermes 6f6d7a6451 Merge pull request #7773 from nesquena/stage/7761-watcher-fence
Release: #7761 gateway watcher stale-projection fence (@franksong2702)
2026-09-23 06:05:11 -07:00
nesquena-hermes 5203e6a5e1 Merge pull request #7772 from nesquena/stage/7758-wakeup-budget
Release: #7758 retryable wake-up refusals keep their delivery budget (@franksong2702)
2026-09-23 05:56:18 -07:00
nesquena-hermes 2930cefc71 Merge pull request #7769 from nesquena/stage/7730-first-visit-locale
Release: #7730 first visit uses the browser locale (@happy5318)
2026-09-23 04:49:56 -07:00
nesquena-hermes 38d0e10fe4 Merge pull request #7768 from nesquena/stage/7165-custom-allowlist
Release: #7165 custom-provider live models allowlist (@happy5318)
2026-09-23 04:40:35 -07:00
nesquena-hermes 3f00824916 Merge pull request #7766 from nesquena/stage/7656-resolve-cap
Release: #7656 configurable full-session resolve concurrency (@happy5318)
2026-09-23 03:49:19 -07:00
nesquena-hermes 5e16dd860f Merge pull request #7764 from nesquena/stage/7708-media-backtick
Release: #7708 stop MEDIA: tokens swallowing a closing backtick (@happy5318)
2026-09-23 02:27:13 -07:00
nesquena-hermes 19b00f5e37 Merge pull request #7762 from nesquena/stage/7749-terminal-handoff
Release: #7749 preserve the chat terminal handoff when the sidebar reports idle first (@franksong2702)
2026-09-23 01:48:58 -07:00
nesquena-hermes 6a41c23cf7 Merge pull request #7757 from nesquena/stage/7751-journal-seq
Release: #7751 allocate run-journal sequence inside the append transaction (@franksong2702)
2026-09-23 01:35:39 -07:00
nesquena-hermes 642230b355 Merge pull request #7756 from nesquena/stage/7748-publication-fence
Release: #7748 fence Agent publication/cleanup with Stop ownership (@franksong2702)
2026-09-23 01:26:49 -07:00
nesquena-hermes b1774b45a9 Merge pull request #7750 from nesquena/stage/rm-346-flakes
Release: #7744 #7742 flaky-test fixes, test-only (@webtecnica)
2026-09-22 21:18:47 -07:00
nesquena-hermes 6f14958bdc Merge pull request #7746 from nesquena/stage/7436-reconnect-replay
Release: #7436 skip redundant reconnect tool-card replay (@atchisonbrent)
2026-09-22 20:28:23 -07:00
nesquena-hermes e0a0e9fbcd Merge pull request #7745 from nesquena/stage/7374-double-render
Release: #7374 stop rendering a settled assistant answer twice (@Thireus)
2026-09-22 20:19:58 -07:00
nesquena-hermes 18db77a132 Merge pull request #7741 from nesquena/stage/rm-343-batch
Release: #7631 sidebar window setting (@carlotestor), #7716 hidden-tab 404 poll (@happy5318), #7734 OpenRouter GLM default (@MuhammadUsamaMX)
2026-09-22 18:15:56 -07:00
nesquena-hermes 65b6e4d390 Merge pull request #7739 from nesquena/stage/7445-readonly
Release: #7445 keep state.db readers strictly read-only and stop idle polling (@ruizanthony)
2026-09-22 16:50:37 -07:00
nesquena-hermes 959177b001 Merge pull request #7737 from nesquena/stage/7569-journal
Release: #7569 run-journal live snapshot rebuild (perf, solo)
2026-09-22 15:38:05 -07:00
nesquena-hermes e14896926f Merge pull request #7736 from nesquena/stage/rm-0922-evening
Release: #6937 launch-failure cleanup, #7021 compression overlap, #7312 profiles Docker 500, #7727 CJK titles
2026-09-22 15:11:23 -07:00
nesquena-hermes 30b407439a Merge pull request #7728 from nesquena/stage/7244-chrono
Ship #7244: chronological state.db row placement (@Hexeption)
2026-09-22 10:33:29 -07:00
nesquena-hermes 91044fc18d Merge pull request #7722 from nesquena/stage/6658-framing
fix(server): close rejected HTTP writes before connection reuse (#6658)
2026-09-22 06:00:04 -07:00
nesquena-hermes e037e1b1bd Merge pull request #7719 from nesquena/stage/7714-profile409
fix(routes): mirror the 409 session_profile_mismatch contract in every profile guard (#7710)
2026-09-22 03:28:26 -07:00
nesquena-hermes b06446cbf5 Merge pull request #7718 from nesquena/stage/7709-badgealias
fix(config): drop synthetic {provider}/{model} alias from configured-model badges (#7290)
2026-09-22 03:17:03 -07:00
nesquena-hermes 25201f9ac6 Merge pull request #7717 from nesquena/stage/7715-login
fix(login): hide the password form when password auth is disabled (#7056)
2026-09-22 03:05:50 -07:00
nesquena-hermes a1f9fb4a78 Merge pull request #7712 from nesquena/stage/7265-nulltool
Release: tolerate null tool_calls in history (#7265)
2026-09-22 00:48:15 -07:00
nesquena-hermes 269ddd5377 Merge pull request #7706 from nesquena/stage/7220-opencode-discovery
Release: opencode-go live model discovery (#7220)
2026-09-22 00:07:53 -07:00
nesquena-hermes b6bbe3da8d Merge pull request #7704 from nesquena/stage/7570-approval-retire
Release: retire producer on gateway approval deny (#7570)
2026-09-21 23:36:01 -07:00
nesquena-hermes cec1431170 Merge pull request #7703 from nesquena/fix/7701-skipall-double-icon
fix(i18n): stop double-rendering the skip-all lightning icon (#7701)
2026-09-21 23:27:10 -07:00
nesquena-hermes d608d03856 Merge pull request #7702 from nesquena/stage/7694-watcher-park
Release: gateway-watcher idle park (#7694)
2026-09-21 23:14:39 -07:00
nesquena-hermes a1805abfb2 Merge pull request #7700 from nesquena/stage/7291-journal-metering
fix(run-journal): keep metering live-only and preserve replay cursors (#7291)
2026-09-21 21:14:44 -07:00
nesquena-hermes c367ef3c05 Merge pull request #7691 from nesquena/stage/7546-steer-compression
Release: steer resolves the active worker after compression (#7546)
2026-09-20 16:22:40 -07:00
nesquena-hermes f6a37b2381 Merge pull request #7678 from nesquena/stage/6962-dispatchable-autocomplete
Release: slash autocomplete announces only WebUI-dispatchable commands (#6962)
2026-09-20 06:20:16 -07:00
nesquena-hermes 173e673c76 Merge pull request #7674 from nesquena/stage/6989-async-wakeup-admission
Release: atomic per-origin async-delegation wakeup admission (#6989)
2026-09-20 04:13:34 -07:00
nesquena-hermes d4a21baa43 Merge pull request #7670 from nesquena/stage/7654-codex-commentary-media
Release: session MEDIA auth + snapshots inspect Codex commentary sidecars (#7654)
2026-09-20 02:26:44 -07:00
nesquena-hermes b09fded7b8 Merge pull request #7668 from nesquena/stage/7401-colon-model-labels
Release: keep custom model names containing colons whole in the picker (#7401)
2026-09-20 00:08:16 -07:00
nesquena-hermes 10003f46d4 Merge pull request #7666 from nesquena/stage/7124-compaction-visibility
Release: keep context compactions visible in long transcripts (#7124)
2026-09-19 21:15:13 -07:00
nesquena-hermes 4aa92dedbd Merge pull request #7664 from nesquena/stage/7649-7630-cron-projects
Release: cron schedule round-trip (#7649) + system-project profile tagging (#7630)
2026-09-19 20:41:33 -07:00
nesquena-hermes f29884d132 Merge pull request #7662 from nesquena/stage/7641-mpf-jpeg
Release: validate MPF JPEG attachments before the redaction exemption (#7641)
2026-09-19 19:49:38 -07:00
nesquena-hermes 0ec876bbf3 Merge pull request #7659 from nesquena/stage/7636-profile-home-cache
Release: profile-home resolve cache (#7636) + access-log stdout independence (#7643)
2026-09-19 18:15:10 -07:00
nesquena-hermes 8c8963321a Merge pull request #7658 from nesquena/stage/7394-7276-tts-redaction
Release: TTS persisted-engine fix (#7394) + session redaction prefilter cache (#7276)
2026-09-19 17:33:19 -07:00
nesquena-hermes dd69bfd9a6 Merge pull request #7639 from nesquena/stage/7618-7619-renderer-i18n
Release: renderer table/italic fixes (#7618) + Extensions panel i18n (#7619)
2026-09-18 16:48:26 -07:00
nesquena-hermes adbb3258ef Merge pull request #7627 from nesquena/release/stage-318
Release exp-v0.52.318: slash-command correctness (#7623, #7511)
2026-09-17 20:25:48 -07:00
nesquena-hermes 2cf8e8a5ea Merge pull request #7626 from nesquena/release/stage-317
Release exp-v0.52.317: documentation accuracy (#7593, #7560)
2026-09-17 16:04:20 -07:00
nesquena-hermes 77323c310e Merge pull request #7624 from nesquena/release/stage-316
Release exp-v0.52.316: zip media delivery (#7612) + Agent moved-name resolution (#7574)
2026-09-17 15:23:59 -07:00
nesquena-hermesandn 06d28c08cb Release: make composer single-row autoResize fast path reachable (#7604) (#7607)
Co-authored-by: n <a@n>
2026-09-16 11:17:36 -07:00
nesquena-hermesandn 03b2be0d38 Release: keep live-follow pinned through above-tail collapse (#7605) (#7606)
Co-authored-by: n <a@n>
2026-09-16 07:07:39 -07:00
nesquena-hermesandn 345ce8baea Release: localize sidebar source-filter tabs (#7602) (#7603)
Co-authored-by: n <a@n>
2026-09-16 02:43:58 -07:00
nesquena-hermesandn 5e5b1178af Release: serve SPA for /sessions route (#7598) (#7601)
Co-authored-by: n <a@n>
2026-09-16 00:31:24 -07:00
nesquena-hermesandn 310265c569 Release: fail closed on missing/unreadable Agent Git identity (#7407) (#7599)
Co-authored-by: n <a@n>
2026-09-15 22:18:23 -07:00
nesquena-hermesandn d98c9be39e Release: staged prefix reads for oversized metadata fields (#7573) (#7597)
Co-authored-by: n <a@n>
2026-09-15 21:29:34 -07:00
nesquena-hermesandn 8d628f4eae Release: route @custom:<slug> models to their own base_url (#7319) (#7592)
Co-authored-by: n <a@n>
2026-09-15 20:10:06 -07:00
nesquena-hermesandn 27b7064c4c Release: decode state.db content sentinel in the message projection (#7492) (#7590)
Co-authored-by: n <a@n>
2026-09-15 17:16:53 -07:00
nesquena-hermesandn 294577a1d1 Release: native composer field-sizing with fallback parity (#6760) (#7589)
Co-authored-by: n <a@n>
2026-09-15 16:56:11 -07:00
nesquena-hermesandn 8fa1244279 Release: nest delegated subagent sessions under their messaging parent (#7263) (#7588)
Co-authored-by: n <a@n>
2026-09-15 16:36:51 -07:00
nesquena-hermesandn 572c84005f Release: preserve remote POSIX workspace paths across session, streaming and upload resolvers (#7168) (#7586)
Co-authored-by: n <a@n>
2026-09-15 15:44:39 -07:00
94fd2da830 Release: semantic fingerprint for the Codex catalog dependency (#7556) (#7558)
* fix(config): semantic fingerprint for the Codex catalog dependency (#7540)

* fix(#7556): guard the recursive codex-cache strip against RecursionError

Codex found a valid-but-deeply-nested models_cache.json crashes
_codex_models_cache_fingerprint with RecursionError (the recursive strip ran
outside the fallback try), 500ing /api/models. Move _strip_volatile_codex_cache_fields
inside the existing encode try/except so a transform failure degrades to the
stat-based fingerprint. +1 mutation-proven regression (forces the strip to raise;
fails with RecursionError if the guard is reverted).

* docs(changelog): stamp #7556 (semantic fingerprint for Codex catalog dependency)

---------

Co-authored-by: webtecnica <webtecnica@gmail.com>
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
Co-authored-by: n <a@n>
2026-09-13 17:39:39 +00:00
nesquena-hermesandnesquena-hermes e36f773891 test(#7510): clean up ruff F401/F841 in the raw-pending-approval test (#7552)
Follow-up to #7551: the merged test file carried an unused `route_approvals as ra`
import and two unused `entry =` assignments (advisory lint gate was red, though not
a required check). Drop them; the two `entry` bindings that are asserted on are kept.

Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-09-13 03:16:48 +00:00
e2ce040f1f Release: actionable ids for raw id-less pending approvals (#7510) (#7551)
* fix(approvals): mint actionable ids for raw id-less local pending entries

A raw id-less approval entry in _pending (agent-side _pending_result drops
{command, pattern_key, pattern_keys, description} verbatim when no gateway
notifier is registered for the session) is unactionable by contract: the
frontend owner-capture requires an approval_id, so the approval card can
neither be approved nor dismissed - the 1.5s poll re-serves it forever.

reconcile_gateway_pending_mirror_locked already mints gwlocal:<token> ids
for id-less _gateway_queues producers; extend the same contract to raw
non-mirror _pending entries with a stable gwlocal-mirrorless:<uuid> id
minted once onto the stored entry dict, so the id persists across polls
and frontend dismiss markers stick.

The exact-id respond path needs no further change: once the entry carries
an id, _resolve_approval_legacy pops it (also clearing the stale
stream-pointer 409 guard), stale explicit ids still fail closed (#527),
and the yolo Skip-all release drains it.

* docs(changelog): stamp #7510 (actionable ids for raw id-less pending approvals)

---------

Co-authored-by: CharlesMcquade <6466275+CharlesMcquade@users.noreply.github.com>
Co-authored-by: n <a@n>
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-09-13 03:07:49 +00:00
e4d9b799e4 Release: manual title regeneration for queued-user transcripts (#7545) (#7547)
* fix(api): scan to first complete exchange for title regeneration (#7543)

_first_exchange_snippets() aborted at a second consecutive user message
before collecting assistant text, so transcripts opening with queued user
rows (channel-backed imports) hit the missing_exchange rejection and the
deterministic fallback got persisted with HTTP 200 — invisible in the UI
and unrecoverable by retrying.

Keep scanning until the first complete user+assistant pair instead, and
fall back to the last complete exchange when the opening user message
yields no user text (privacy scrubbing) instead of failing with
empty_user_message.

Tests: tests/test_issue7543_title_first_exchange.py (8 cases, incl. the
issue-pinned transcript shape and walker-mocked discriminator tests for
both fixes).

* test(api): drop local-machine notes and sys.path hack from 7543 test module

- Docstring described the change as a local-only uncommitted hotfix with
  machine-specific paths — wrong for an upstream PR and unsafe to publish.
- Drop the defensive REPO_ROOT sys.path insert; the repo conftest already
  puts the package root on sys.path (matches the neighboring test modules).

* fix(api): drop unreachable latest-exchange fallback from title regeneration

Greptile flagged the mocked-walker fallback test (P2) as fabricating
internal state, and an exhaustive enumeration of realistic transcript
shapes (5460 combinations, lengths 1-6) confirms it: both walkers share
the same text extraction and the forward walker scans every message, so
'first walker empty while latest walker yields a pair' is unreachable
from real transcripts. The fallback branch was dead code.

Remove it together with its two walker-mocked tests; the fixed first-
exchange walker alone resolves the reported issue shape. Replace the
mocked tests with an observable E2E error-path test through the real
walkers, and make the aux mock guard-faithful (empty assistant_text ->
missing_exchange per the generate_title_raw_via_aux contract) so the
fail-before proof actually exercises the endpoint contract.

* fix(#7543): scope first-exchange scan-past to the manual-regen path only

The full suite caught that broadening the SHARED _first_exchange_snippets also
activated the automatic in-stream background-title path for consecutive-user-row
transcripts, moving stream teardown from the synchronous stream_end branch to the
background-title-thread branch (test_issue3929 emits_done regressed: stream_end
was no longer in the synchronous queue). #7543 is specifically about the MANUAL
'Regenerate title' endpoint, so gate the scan-past behavior behind an opt-in
scan_past_consecutive_users flag (default False = master behavior) and pass True
only from generate_session_title_for_session. Auto in-stream path is now
byte-identical to master; added a default-behavior regression guard test.

* docs(changelog): stamp #7545 (manual title regen for queued-user transcripts)

---------

Co-authored-by: Raylands <Raylands@users.noreply.github.com>
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
Co-authored-by: n <a@n>
2026-09-12 21:12:52 +00:00
b1286878a4 Release: models_discovered/discover_models live-catalog fix (#7409) (#7538)
* Apply reviewed change

* fix(models): honor discover_models opt-out + preserve discovered catalog on live-probe failure

Codex gate found two CORE edge cases in the #7404 fix:
1. discover_models:false must override models_discovered:true (explicit opt-out
   pins the configured allowlist; honor Agent string forms false/no/0).
2. a transient empty live-catalog probe dropped a discovered provider's models
   (cached empty ~24h); now falls back to configured discovered IDs merged with
   any static catalog (deduped, ordered first).

Mirrors the Hermes Agent canonical semantics (model_switch_providers._discover_flag,
model_switch._models_config_is_allowlist). Adds 3 mutation-proven regressions.

* docs(changelog): stamp #7409 (models_discovered/discover_models live catalog)

---------

Co-authored-by: evgenyponomarev <712802+evgenyponomarev@users.noreply.github.com>
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
Co-authored-by: n <a@n>
2026-09-12 05:32:16 +00:00
nesquena-hermes 52bcfa3cb9 Merge pull request #7537 from nesquena/stage-relmgr-0912c
exp-v0.52.299 — graceful SIGINT shutdown (#7315)
2026-09-11 20:28:03 -07:00
nesquena-hermes 00afa1eb31 Merge pull request #7536 from nesquena/stage-relmgr-0912a
exp-v0.52.298 — static MIME types (#7372) + upload TOCTOU (#7337)
2026-09-11 18:49:42 -07:00
nesquena-hermesandnesquena-hermes 2ad70a2815 docs(changelog): stamp #7525 (restore cron delivery platforms) (#7527)
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-09-11 05:32:02 +00:00
nesquena-hermesandnesquena-hermes f79325498e fix(cron): restore messaging platforms in the delivery picker (#7525)
* fix(cron): restore messaging platforms in the delivery picker

The Agent moved _KNOWN_DELIVERY_PLATFORMS from cron.scheduler to
cron.scheduler_delivery. _handle_cron_delivery_options imported the old
path inside a bare except and fell back to an empty frozenset, so the
import error was swallowed and GET /api/crons/delivery-options silently
returned only local and origin — telegram, discord, slack, feishu and
every other messaging platform disappeared from the cron delivery picker
with no error surfaced anywhere.

Resolve the authority across both module paths (current first, legacy
fallback) so the picker keeps working across Agent versions, and add a
regression test that pins the resolution order and cross-checks the
endpoint output against the resolved authority.

* test(cron): skip the authority-resolution test where the Agent is absent

CI runs agent-free (tests/browser_smoke.py), so neither cron.scheduler_delivery
nor cron.scheduler is importable there and the authority resolves empty. The
new regression test asserted non-empty and therefore failed shard 3 on both
Python versions. Skip instead: with no cron package there is no authority to
resolve and nothing meaningful to assert. The test still fails loudly wherever
the Agent IS installed, which is where a future relocation would bite.

* test(cron): register the new test in _AGENT_DEPENDENT_TESTS

Use the project's existing skip mechanism (tests/conftest.py) rather than an
ad-hoc inline pytest.skip, matching the five sibling delivery-options tests.
CI runs agent-free, so there is no cron package and no authority to resolve
there; with the Agent installed the test still asserts loudly, which is the
environment where a future relocation would actually bite.

Verified both directions: 6/6 pass with the Agent present, and forcing
AGENT_MODULES_AVAILABLE=False skips all 6 (was 5) as CI will.

---------

Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-09-10 22:30:57 -07:00
nesquena-hermesandnesquena-hermes 88b8e7450a docs(changelog): stamp #7519 + #7522 (auxiliary model picker fixes, thanks @webtecnica) (#7526)
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-09-11 05:17:11 +00:00
nesquena-hermes b7d81ce89e Merge pull request #7522 from webtecnica/fix/7521-aux-picker-endpoint-error-groups
fix(settings): keep endpoint-error provider groups in the auxiliary model pickers (#7521)
2026-09-10 22:13:23 -07:00
nesquena-hermes c5315bda6a Merge branch 'master' into fix/7521-aux-picker-endpoint-error-groups 2026-09-10 22:07:56 -07:00
nesquena-hermes f6f344063d Merge pull request #7519 from webtecnica/fix/7486-aux-provider-preserve
fix(settings): preserve configured aux provider when absent from catalog (#7486)
2026-09-10 22:07:26 -07:00
nesquena-hermes 80eb26301c Merge branch 'master' into fix/7486-aux-provider-preserve 2026-09-10 22:03:09 -07:00
nesquena-hermesandnesquena-hermes ce483fc70f docs(changelog): stamp #7518 (OpenRouter z-ai/ namespace, thanks @webtecnica) (#7524)
Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com>
2026-09-11 04:52:39 +00:00
nesquena-hermes 8cd1e544ed Merge pull request #7518 from webtecnica/fix/7514-openrouter-zai-namespace
fix(onboarding): use OpenRouter namespace z-ai/ for Z.AI models (#7514)
2026-09-10 21:50:59 -07:00
nesquena-hermesandn b0f1536f87 Release exp-v0.52.294: add GLM-5.3 Flash to Z.AI catalog (#7323) (#7517)
Co-authored-by: n <a@n>
2026-09-10 20:10:08 +00:00
nesquena-hermesandn f4569ade88 Release exp-v0.52.293: extract _handle_session_get refactor (#7340) (#7516)
Co-authored-by: n <a@n>
2026-09-10 19:50:42 +00:00
nesquena-hermesandn a71f6c6feb Release exp-v0.52.292: recovered-reasoning-card duplication fix (#7443) (#7513)
Co-authored-by: n <a@n>
2026-09-10 19:30:53 +00:00
nesquena-hermes 71689c6ce7 Merge pull request #7505 from nesquena/release/pr7398-keycmd-cache
Release: preserve agent cache for key_cmd credentials (#7398)
2026-09-09 22:49:15 -07:00
394ab31eea release: #7351 bind turn workspace as agent cwd (#7504)
* rebase #7351 onto master (bind turn workspace as agent session cwd)

Co-authored-by: samfoy <samfoy@users.noreply.github.com>

* fix test: use deployed agent.runtime_cwd API (_SESSION_CWD.get) not nonexistent _session_cwd_override

The two failing assertions referenced agent.runtime_cwd._session_cwd_override(), a
helper not present in the installed Agent (which exposes _SESSION_CWD, resolve_agent_cwd,
set/clear_session_cwd). The production binder is correct and verified: binding workspace=/tmp
sets _SESSION_CWD.get()=='/tmp' and resolve_agent_cwd()=='/tmp', reset restores _UNSET.
Line 343 was redundant with the surrounding assertions; line 386 now reads _SESSION_CWD.get().

Co-authored-by: samfoy <samfoy@users.noreply.github.com>

* docs(changelog): stamp #7351 turn workspace cwd binding

---------

Co-authored-by: n <a@n>
Co-authored-by: samfoy <samfoy@users.noreply.github.com>
2026-09-10 03:40:45 +00:00
47e394895d release: #7160 stale-runtime report + hardened Agent-update marker read (#7502)
* rebase #7160 onto master (report unverified Agent updates, no auto-restart)

Co-authored-by: hrdwdmrbl <hrdwdmrbl@users.noreply.github.com>

* harden agent-update marker read: no-follow, fstat regular-file, bounded (fixes gate CORE)

The Agent update marker is attacker-adjacent shared state. _read_live_agent_update()
used Path.read_text(), which follows symlinks, blocks forever on a FIFO, and reads an
unbounded regular file — a rejected/stale-runtime request could hang or OOM. Now opens
O_RDONLY|O_NONBLOCK|O_NOFOLLOW, fstat-verifies a small regular file, and reads a bounded
max, classifying anything else as 'unknown' (fail-closed). Adds FIFO/oversized/symlink/
happy-path regression tests.

Co-authored-by: hrdwdmrbl <hrdwdmrbl@users.noreply.github.com>

* fix marker-read portability: gate os.open fast-path on O_NONBLOCK+O_NOFOLLOW

os.O_NONBLOCK is Unix-only; accessing it unconditionally raised AttributeError
on native Windows, breaking every stale-revision barrier (chat/compression/etc).
Now both flags resolve via getattr and the os.open() fast path is taken only
when BOTH are available (_MARKER_SAFE_OPEN_AVAILABLE); otherwise fall back to an
lstat-only classification (absent vs unknown) so a fallback platform can never
symlink-traverse or crash. Adds a Windows-fallback regression test.

Co-authored-by: hrdwdmrbl <hrdwdmrbl@users.noreply.github.com>

* docs(changelog): stamp #7160 stale-runtime report + hardened marker read

---------

Co-authored-by: n <a@n>
Co-authored-by: hrdwdmrbl <hrdwdmrbl@users.noreply.github.com>
2026-09-10 02:21:04 +00:00
nesquena-hermes ae311e4377 Merge pull request #7500 from nesquena/release/exp-v0.52.288-bound-sidebar-cache
exp-v0.52.288: bound sidebar session-list cache
2026-09-09 17:23:57 -07:00
cfdfe4db8f release: #7261 provider-native auxiliary model IDs (approved) (#7491)
* fix(settings): persist provider-native auxiliary model IDs

Co-authored-by: lowlandsheperd <lowlandsheperd@users.noreply.github.com>

* docs(changelog): stamp #7261 provider-native aux model IDs

---------

Co-authored-by: n <a@n>
Co-authored-by: lowlandsheperd <lowlandsheperd@users.noreply.github.com>
2026-09-09 20:49:47 +00:00
351f664021 release: #7317 workspace switcher stored order (approved) (#7490)
* fix: workspace selector follows Workspaces view order (drop alpha re-sort)

Co-authored-by: CharlesMcquade <CharlesMcquade@users.noreply.github.com>

* docs(changelog): stamp #7317 workspace switcher stored-order

---------

Co-authored-by: n <a@n>
Co-authored-by: CharlesMcquade <CharlesMcquade@users.noreply.github.com>
2026-09-09 20:38:57 +00:00
2477d992f4 release: lock-disciplined STREAMS reads (#7339) (#7488)
* fix(streaming): lock-disciplined STREAMS reads via peek_stream()

Writers pop STREAMS under STREAMS_LOCK, but four hot reads used bare
STREAMS.get(): the streaming worker start, the gateway run start, and the two
SSE attach paths in routes.py. Each is individually saved today by GIL-atomic
dict.get plus a None-guard, but the check-then-act windows (get → register,
get → subscribe) race teardown pops, and the bare pattern invites unprotected
copies. peek_stream() centralizes the locked read; all four sites migrate with
no behavioral change.

* test: dual-patch config.STREAMS alongside routes.STREAMS in SSE seam tests

peek_stream() reads the canonical api.config.STREAMS registry; tests that
inject a fake registry by patching only the routes-level re-export left the
helper reading the real (empty) registry and hung the SSE loop to the
pytest-timeout ceiling. Mirror the test_issue6623 pattern: patch both
bindings.

* docs(changelog): stamp #7339 lock-disciplined STREAMS reads

---------

Co-authored-by: Sebastian B <sb@wmc.sh>
Co-authored-by: n <a@n>
2026-09-09 20:22:36 +00:00
b1a5ade137 release: multimodal title-generation fix (#7306) (#7484)
* fix(title): preserve multimodal title generation

Assisted-by: Hermes Agent:gpt-5.6-sol
Assisted-by: Codex:gpt-5.6-luna
Assisted-by: Claude Code:claude-opus-5

* docs(title): explain multimodal title generation

Assisted-by: Hermes Agent:gpt-6-astra

* docs(changelog): stamp #7306 multimodal title-generation fix

---------

Co-authored-by: starship-s <45587122+starship-s@users.noreply.github.com>
Co-authored-by: n <a@n>
2026-09-09 18:50:13 +00:00
842b2ac471 release: composer footer-fit jitter fix (#7275) (#7483)
* fix(composer): stop footer fit from jittering the transcript during SSE

_fitComposerFooter() measured overflow by REMOVING the .cf-icons/.cf-burger
stage classes, reading scrollWidth, then adding them back. Between those two
steps the footer is laid out at full width: the composer grows a few px and
#messages loses the same amount of clientHeight, then gets it back on the
next frame.

For a pinned reader that is a visible up/down jitter of the whole transcript,
because the fit pass runs on every context-indicator update — which fires
continuously while an SSE turn is streaming.

Measured with a real Chromium probe instrumenting the scrollTop setter,
scroll events, ResizeObserver and MutationObserver:

  before: 4 non-JS backward jumps of exactly -8px per streamed turn,
          each one ~30ms after a `ctx-indicator-wrap` -> `composer-footer`
          class mutation pair
  after:  0 backward jumps over 5 streamed turns on 2 different sessions

Fix: freeze the footer's layout box (explicit height + visibility:hidden)
for the duration of the measurement, so the intermediate expanded geometry
is never committed to the screen, and restore the resolved stage in the same
task. The adaptive behaviour is unchanged — verified across 8 viewport
widths (1600 -> 420px), with the correct full/icons/burger stage at each and
no residual inline style left behind.

Note: the guard added in the tail-jitter work is what keeps the reader pinned
here; before it, the same footer jitter unpinned the reader instead, which
masked the oscillation behind a worse bug.

* test(composer): cover footer fit freeze across full/icons/burger stages

Add a behavioural node driver test for _fitComposerFooter() that runs the
actual function from static/ui.js against a small layout model where the
stage classes dictate the footer's natural height and the left cluster's
content width. Every class mutation, inline-style write and overflow
measurement commits a layout sample, so the recorded footer heights and
messages clientHeights are what a browser would have painted.

The matrix starts from each stage (full, icons, burger), forces each
overflow outcome, and runs with empty and caller-owned prior inline
styles. It asserts the resolved stage classes, that the footer border-box
height and messages clientHeight stay pinned while the ladder is probed
(and do not move at all in the steady state), that no intermediate stage
is ever painted, and that prior inline height/visibility are restored
verbatim. It also covers the zero-height skip and an exception during
measurement, and includes a control run with the freeze made ineffective
to prove the harness reports the original jitter. Against the pre-fix
ui.js the height, jitter, painted-stage and style-restoration assertions
fail.

* docs(changelog): stamp #7275 composer footer-fit jitter fix

* ci: re-trigger (playwright browser install hung on GH runners)

* ci: re-trigger (google chrome apt mirror hash-sum mismatch, external infra)

---------

Co-authored-by: Anthony Ruiz <ruizanthony@users.noreply.github.com>
Co-authored-by: n <a@n>
2026-09-09 18:11:21 +00:00
nesquena-hermes b1792e64e7 Merge pull request #7480 from nesquena/stage/7270
Release exp-v0.52.282: canonical server entrypoint for Windows restart (#7270, @rodboev)
2026-09-08 23:38:46 -07:00
nesquena-hermes ec63149e81 Merge pull request #7479 from nesquena/stage/7336
Release exp-v0.52.281: reject malformed/non-object JSON bodies with clean 400s (#7336, @zicochaos)
2026-09-08 21:44:39 -07:00