50 Commits
Author SHA1 Message Date
t 0e2fe7c3eb changelog: #5792 restore CSV media download affordance 2026-07-10 21:34:04 +00:00
tandruizanthony 8949cad20f Merge #5792: keep media downloads visible in CSV previews
Co-authored-by: ruizanthony <ruizanthony@users.noreply.github.com>
2026-07-10 21:33:41 +00:00
tandrodboev 3188f88599 fix(#4812): break live SSE loop on a terminal event even when deduped at cutoff
Codex round-3 finding #2 [CORE]: when reconciliation replayed the active run's
terminal event at the subscribe cutoff, the live queue's copy hit the cutoff/dedup
'continue' BEFORE the terminal 'break' check — so the handler never broke, stayed
blocked on the dead run's queue, and missed subsequent session runs. Check the
terminal event type before the already-delivered continue: a terminal always ends
the loop (after emitting if not already sent). Regression test asserts the handler
unsubscribes (doesn't hang) when the terminal is deduped. 24/24 SSE tests green.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:47:06 +00:00
tandrodboev 2b22690fa4 fix(#4812): capture resume cursor + journal baseline before SSE headers commit
Codex round-3 finding #1 [SILENT]: baselining after end_sse_headers() left a window
where a run completing between header commit and baseline was absorbed into the
baseline + silently lost. Move resume-id parse + fingerprint baseline before
send_response/headers (both side-effect-free: header read + stat-only fingerprint).

Codex round-3 also flagged finding #2 [CORE] (reconciliation terminal-event-at-cutoff
dedup keeps the handler attached to a dead run queue) — NOT addressed here; escalating
to Nathan per Codex-depth diminishing-returns (3rd round into the same SSE seam class).

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:44:10 +00:00
tandrodboev 3c642e08f1 fix(#4812): hoist idle SSE fingerprint baseline to earliest point (before preliminary lookup + initial replay)
Codex re-gate found the baseline was still after the preliminary
_active_run_stream_for_session() lookup + the initial cursor read_session_run_events()
replay — a run completing during either window folded into the baseline and was
silently missed. Move the fingerprint baseline to immediately after resume_event_id
parsing, before both operations, so no pre-baseline completion window remains. Remove
the now-redundant later baseline. 23/23 SSE tests green.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:36:22 +00:00
tandrodboev 3ac19a5518 fix(#4812): capture idle SSE fingerprint baseline BEFORE first attach (TOCTOU)
Final-gate Codex caught a TOCTOU race in the prior idle-seam fix: the fingerprint
baseline was captured AFTER the first attach_active_stream() lookup, so a run
completing DURING that first attach folded into the baseline and was silently
missed (only : keepalive emitted, no snapshot). Move the baseline capture before
the first attach so any completion from that point on is detected. Add an ordering
regression test (baseline fp precedes the idle-loop attach + advance still emits
one snapshot). 23/23 SSE tests green.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:24:47 +00:00
tandrodboev 2829843a2a fix(#4812): re-sync idle no-cursor SSE subscriber on run completing during keepalive wait
Fable gate found a seam Codex's 3 boundary findings didn't cover: an idle no-cursor
subscriber to /api/sessions/{id}/events misses a run that starts AND finishes inside a
single keepalive tick — the wait loop only looked for a live in-memory STREAMS entry to
attach, never noticing the journal advanced, so the run's transcript was silently missing
until manual refresh.

Add a cheap bounded session_journal_fingerprint() (file-count/max-mtime/total-size from
stat only, never parses bodies) and, inside the idle attach-wait loop, emit a session_snapshot
re-sync whenever the fingerprint advances with no live stream to attach — the same honest
recovery contract used for a failed reconciliation. Re-baselines after each re-sync so a quiet
idle connection never spams snapshots. 2 regression tests; 22/22 SSE tests green.

Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:15:49 +00:00
tandrodboev 9600e1546a Merge #5677: resumable session SSE stream (#4812)
Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 20:12:27 +00:00
t d967131056 fix(#3929 ux): gate wakeup-pause disclosure on actual pause + cover both error paths
Codex re-gate caught 2 defects in the prior UX commit:
1. streaming.py:8921 — the disclosure fired for ANY process_wakeup failure (e.g.
   rate-limit) even when no pause was recorded -> falsely claimed 'retries paused'
   while process_wakeup_pause stayed empty. Now gated on the record_* return value.
2. streaming.py:10130 — the raised-exception credential_pool_empty path (exercised
   by the existing agent test) recorded the pause but omitted the disclosure. Added
   the same conditional disclosure there.
Both paths now keep _error_payload['hint'] in sync with the persisted bubble, and
the disclosure appears only when a pause was actually recorded. 69 tests green.
2026-07-10 19:28:06 +00:00
tandfranksong2702 c26bc21194 ux(#3929): disclose wakeup pause in error card + changelog
Fable UX-gate follow-up on #5732: after the first credential-exhausted error,
automatic wakeups are silently suppressed. Disclose it in the wakeup-source
error card ('Automatic retries for this conversation are paused until you send
a message, switch the model/provider, or fix the credentials.') so the silence
reads as intentional, not a stuck agent — Gmail/Dropbox account-needs-attention
convention. Scoped to the process_wakeup + credential_pool_empty seam only.

Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-07-10 19:16:48 +00:00
tandfranksong2702 669ddde4b0 Merge #5732: pause credential-exhausted process wakeups (#3929)
Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
2026-07-10 19:10:49 +00:00
t d690eb0cdb changelog: #5887 focus composer after URL deep-link prefill 2026-07-10 18:45:38 +00:00
tandrodboev 78cc5557b0 Merge #5887: focus composer after URL prefill
Co-authored-by: rodboev <rodboev@users.noreply.github.com>
2026-07-10 18:45:20 +00:00
t 7f613d3c76 changelog: #5889 stale-session-load pane isolation + #5882 fail-closed OpenRouter pricing 2026-07-10 17:54:21 +00:00
tandstarship-s 4a4a6d4927 Merge #5889: fix stale session loads contaminating the active pane
Co-authored-by: starship-s <starship-s@users.noreply.github.com>
2026-07-10 17:53:55 +00:00
tandigorroncevic b6c7a36750 Merge #5882: fail closed on incomplete OpenRouter pricing
Co-authored-by: igorroncevic <igorroncevic@users.noreply.github.com>
2026-07-10 17:53:55 +00:00
t 5a3b4146b8 Merge branch 'pr-5557' into release/stage-5557 2026-07-09 06:28:22 +00:00
t c81463a30d Merge branch 'pr-5803' into release/stage-5803 2026-07-09 06:05:44 +00:00
t 046a0d6bcb lint: drop unused pathlib.Path import in test_update_channels (ruff F401) 2026-07-08 20:28:15 +00:00
t 43afc498b8 test+style: fix 2 full-suite regressions from the channel edits
- test_api_timeout: assert the updates/check call keeps timeoutMs:60000 in its
  new _checkBody form (functionally identical; still the 60s override)
- panels.js: reword two // comments to drop apostrophes — the smooth-text-fade
  brace-matcher test treats ' in a comment as a string delimiter and lost
  loadSettingsPanel's closing brace (node --check confirms the JS was always valid)
2026-07-08 20:18:10 +00:00
t 99bd2930cc fix(updates): mobile badge ellipsis needs display:block (Fable r2)
text-overflow:ellipsis is a no-op on the inline-flex badge; display:block in the
<=768px rule makes the ellipsis actually render for a long experimental describe.
2026-07-08 20:06:34 +00:00
t 0a56f44f5e fix(updates): Fable UX gate — channel re-check race + copy + mobile badge
MUST-FIX: /api/updates/check now accepts an explicit 'channel' in the POST body;
the Settings dropdown passes the just-picked value to checkUpdatesNow(channel) so
the immediate re-check can't race the debounced autosave PUT and answer for the
previous channel (verified live: body channel wins over stale saved setting).

SHOULD-FIX:
- copy: 'soaked' -> 'soak-tested'; append 'Applies to WebUI updates only.' to the
  channel helper text (all 15 locales, native translations)
- mobile: .settings-version-badge gets max-width/overflow/ellipsis in the <=768px
  query so the '· Experimental' suffix can't overflow a 320px viewport

(#5 badge-suffix i18n key deferred — non-blocking fast-follow per Fable, matches
the existing English-only version badge on master.)
2026-07-08 20:01:39 +00:00
t 0168bd1aed fix(updates): apply_clear_lock preserves the configured channel
Codex round-2 gate: apply_clear_lock re-entered _apply_update_inner(target)
without the channel, so an experimental WebUI lock-recovery retry silently fell
back to stable. Now passes _read_update_channel() through. + regression test.
2026-07-08 19:53:32 +00:00
t 162e145c30 fix(updates): channel is WebUI-only — never leak it to the Agent repo check/apply
Codex gate CORE fix: check_for_updates passed the user's WebUI channel into the
Agent repo resolution, so on 'experimental' the Agent ignored its v* tags and
fell back to origin/master. The Agent is a separate project (plain v* tags,
tracks master past tags) and must ALWAYS use DEFAULT_UPDATE_CHANNEL. Forced in
all 3 sites: check_for_updates agent leg + _apply_update_inner + apply_force_update
(target=='agent' -> channel=DEFAULT_UPDATE_CHANNEL). Added a real-git regression
proving Agent release/apply resolution is identical under both WebUI channels.
2026-07-08 19:49:36 +00:00
t bf5e5a0d3d test(updates): fix channel-signature fallout + add i18n keys to all 14 locales
- test_update_stash_recovery: add merge-base handler for the force-update
  rewind guard probe (origin/master is a descendant of HEAD -> not a rewind)
- test_security_review_fixes: fake_check accepts channel kwarg
- i18n.js: native translations of the 4 update-channel keys for all 14
  non-English locales (locale-coverage tests enforce key presence)
2026-07-08 19:37:44 +00:00
t 2cf43527a3 feat(updates): stable/experimental release channels
Add an update_channel setting (stable|experimental) that selects which git-tag
stream the self-updater tracks on the single linear master line:

  stable       -> 'v*'      promoted, soaked releases (default; unchanged glob)
  experimental -> 'exp-v*'  every release batch (opt-in testers)

A channel is only a tag glob — no branches, no divergence — so every ff-only
guarantee (#2653/#2846/#3140) is preserved. Channel governs the WebUI repo only;
the Agent repo keeps its historical branch fall-through.

Correctness (advisor-reviewed, Codex + Fable):
- describe uses --match <glob> so a commit tagged both v* and exp-v* resolves
  to the channel-correct tag
- stable never falls through to origin/master when HEAD contains the latest
  stable tag (the firehose-suppression that makes channels work)
- apply_force_update refuses to reset --hard onto an ancestor ref (rewind guard)
- update cache + in-progress guard keyed by (channel, include_agent)
- channel display badge is a SEPARATE field; WEBUI_VERSION stays channel-neutral
  (asset cache-busting / SW cache / stale-client skew all do exact-string equality)

Settings UX: channel dropdown with risk-forward copy + the ff-only asymmetry
helper ('switching back to Stable keeps your current version until Stable catches
up'), channel chip on the version badge, i18n keys, re-check on switch.

Tests: new tests/test_update_channels.py (12 real-git-fixture tests) + existing
update suite updated for the channel-aware signatures.
2026-07-08 19:25:27 +00:00
t 64cee6165d stage 5717 on current master 2026-07-07 01:34:14 +00:00
t 7fbb9bc98d docs(changelog): stamp #5664 workspace file-tree scroll preserve 2026-07-06 23:25:27 +00:00
t 4b93510ef6 stage 5664 on current master 2026-07-06 23:14:53 +00:00
t 30073740a4 docs: full accuracy refresh of ROADMAP.md
The roadmap had drifted ~120 releases (stamped v0.51.792, current is
v0.51.911) and was missing entire surfaces the project now ships. This is
a full pass to make every section reflect what actually exists today.

What changed:

- Status snapshot rewritten: adds the extension system, the native-client
  fleet (macOS/Windows/Linux/Android/iOS), i18n, gateway, and autonomous
  maintenance as first-class rows.
- Skins corrected 11 -> 21 (authoritative _SKINS array in boot.js); base
  model restated as 3 modes (Light/Dark/System) x 21 skins, dropping the
  stale legacy "8 themes" list (solarized/monokai/nord/oled are legacy
  aliases mapped onto skins, not standalone skins).
- Locales 14 -> 15 (adds Czech); note full non-English coverage.
- Gateway platforms expanded to include WeChat/Weixin, Signal, SMS.
- New "Extension system" checklist section: loader, one-click gallery,
  manifest contract, theme/TTS/nav/sidecar capabilities, settings schema +
  owned storage, trust model, and the vetted library repo.
- New "Native clients" section: per-repo table for hermes-swift-mac,
  hermes-desktop-rust (Tauri), hermes-android, hermes-swift-ios. No version
  numbers (they drift per repo).
- New "Autonomous project maintenance" section pointing at StewardOS.
- Chat/sessions/workspace/cron/security/mobile checklists updated with the
  many features shipped since the last stamp (Steer default, Transparent
  Stream, compression-recovery, cron fork, schedule builder, self-hosted
  provider from Settings, copy-relative-path, CORS/open-redirect hardening,
  mobile scroll hardening, stable sidebar grouping, etc.).
- Forward work pruned: ~20 of the ~30 listed issues have shipped and were
  removed; remaining list is the actually-open set (verified live via gh).
  Marketplace moved out of "not planned" (the extension system fills it);
  added multi-tenant/white-label to "not planned" per project scope.
- Removed the hardcoded version/test-count stamp from the header in favor
  of live-derivation pointers (matches the rest of the docs).
2026-07-06 22:23:09 +00:00
t 9ae4ec8f09 docs(changelog): stamp #5688 self-update lock recovery 2026-07-06 21:46:39 +00:00
t e2184b7b12 stage 5688 on current master (post parallel release) 2026-07-06 21:45:49 +00:00
t cec093eef6 test: fix chronic full-suite agent/hermes_cli __path__ isolation poison (2 flakes)
Convert in-place pkg.__path__=[] mutations on the REAL agent/hermes_cli
packages to monkeypatch.setattr (auto-restored), and make
test_issue1574's _activate_spawn_fake_agent snapshot+restore the
HERMES_WEBUI_AGENT_DIR/PYTHONPATH/sys.path it mutates.

Fixes:
- test_v050259_sessiondb_fd_leak::test_session_db_close_is_idempotent
- test_tls_support::test_tls_startup_failure_fallback_to_http
2026-07-06 21:08:52 +00:00
t 5df8a06800 fix(#5696): revert profiles cache TTL 60s->4s (stale profile rows); contributor-flagged follow-up 2026-07-06 20:40:08 +00:00
t 36176a9ee4 docs(changelog): stamp #5696 session-load perf 2026-07-06 20:21:04 +00:00
t 2454719f2e gate 5696 + fold-in: non-throwing HERMES_DEBUG_SLOW parse (Codex CORE fix) 2026-07-06 20:15:42 +00:00
t 06590556f5 gate 5696 on current master 2026-07-06 20:05:17 +00:00
t 1a71779952 docs(changelog): stamp #5674 sidebar lineage grouping stability 2026-07-06 18:21:13 +00:00
t d7b01185ac chore: drop .claude pr-sweep proof artifact from release (gitignored, not for public repo) 2026-07-06 18:20:45 +00:00
t c1c26ca4aa test merge 5674 2026-07-06 18:20:03 +00:00
t 2283babbba docs(changelog): stamp #5672 content-visibility scrollHeight root fix 2026-07-06 18:05:03 +00:00
t efe768fb17 test merge 5672 on master w/ 5685+5681+5666 2026-07-06 17:59:15 +00:00
t 5b4397e9de docs(changelog): stamp #5666 mobile stale-anchor stream nudge fix 2026-07-06 17:48:11 +00:00
t a7b9b2a132 test merge 5666 on master w/ 5685+5681 2026-07-06 17:47:30 +00:00
t db231464c8 docs(changelog): stamp #5681 unpinned-reader scroll-jump fix 2026-07-06 17:37:15 +00:00
t 3cbca94f9c test merge 5681 on post-5685 master 2026-07-06 17:36:12 +00:00
Dhaval d9293c6097 refactor: streamline model provider resolution in chat start handler 2026-04-02 09:14:21 -07:00
Dhaval 669412cbc9 refactor: switch from requests to urllib for custom endpoint model fetching 2026-04-02 09:14:21 -07:00
Dhaval c1a9324f35 feat: add support for Ollama and LM Studio providers in model fetching 2026-04-02 09:14:21 -07:00
Dhaval cbf82898cb feat: implement custom endpoint fetching for model lists and update streaming handler 2026-04-02 09:14:21 -07:00