Commit graph

251 commits

Author SHA1 Message Date
AJV20
b53bc1a2ea fix: harden webui passive performance paths 2026-05-30 01:39:54 +00:00
george-andraws
317d828cff Add clear button to conversation filter 2026-05-30 00:52:29 +00:00
nesquena-hermes
9059b8f5c3 Merge PR #3116 (stale unread + compression timer + tool-card dedup) into stage-batch43 2026-05-30 00:21:04 +00:00
mysoul12138
0002cda23d fix: stale unread dot, compression timer leak, tool card duplication (#3020, #2973)
#3020: Sync viewed-count in the polling path for actively-viewed sessions
so navigating away doesn't show a stale unread dot. Defensive clear of
completion-unread marker in _setSessionViewedCount.

#2973: Clear elapsed-timer attributes and interval when a live compression
card transitions from running to done, preventing the orphan timer from
overwriting the completed card state. Guarded by active-session check.

Tool card duplication: Route tool_complete result to tc.snippet (detail)
instead of tc.preview (header) to prevent identical content appearing in
both the card header and expanded detail section.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 00:20:49 +00:00
Sanjays2402
01c27806d4 Fix #3018: preserve per-turn ephemeral fields across session refreshes
`_turnUsage` (and `_turnDuration`, `_turnTps`, `_gatewayRouting`,
`_statusCard`) are computed client-side in `_finishDone()` and attached
to the last assistant message in `S.messages`. Three code paths replace
`S.messages` wholesale with fresh API data that lacks these fields:

  1. `_restoreSettledSession()` after a late `stream_end` or SSE error.
  2. The late-restore branch after `done` (messages.js ~L2247).
  3. `loadSession()` for active-session external refresh / focus-change.

When any of these fire after `done`, the badge/duration/gateway-pill
flashes for ~1s and disappears, never returning until the next message
or page reload.

Add `_carryForwardEphemeralTurnFields(prev, next)` that matches messages
by `(role, timestamp, content prefix)` — the same identity the renderer
already uses — and copies forward the ephemeral fields when the server
payload is missing them. Wire it into all three replace sites. The fix
is conservative: it only fills slots that are `null` on the new message,
so an authoritative server-side value (if/when the API ever surfaces
per-turn usage) wins automatically.

Picked Option A from the bug report (preserve on the client side) over
Option B (synthesize from `S.lastUsage`) because `lastUsage` is a
session-level aggregate; reconstructing per-turn breakdowns from it is
lossy. Option C (set `_streamFinalized` earlier) would suppress legit
late-arriving server data on transient errors.
2026-05-30 00:11:50 +00:00
Sanjays2402
7c3d85d6c5 Fix #3107: throttle active-session external-refresh poll from 5s to 30s
The active-session 'is it externally updated?' fallback poll fires every
5 s. On long sessions this causes visible scroll churn (the rendered
message list is rebuilt and the scrollTop is restored on a 5-second
cadence) and a measurable network/CPU floor even when the user is just
reading.

This poll is a *fallback* for the case where the SSE session-events
stream is unavailable; SSE already invalidates the active session in
real time. Pushing it to 30 s keeps the safety net for SSE-broken
environments without it acting as a primary refresh path.

Regression introduced in 467ef33a.
2026-05-29 03:25:49 -07:00
AJV20
2cb3c9f10b Merge remote-tracking branch 'origin/master' into HEAD
# Conflicts:
#	CHANGELOG.md
#	tests/test_workspace_git.py
2026-05-28 14:50:33 -04:00
nesquena-hermes
2f73eb0f8d Merge PR #3039
# Conflicts:
#	CHANGELOG.md
2026-05-28 18:27:03 +00:00
AJV20
cf6e3111c4 Merge remote-tracking branch 'origin/master' into fix/webui-bugfix-sweep
# Conflicts:
#	CHANGELOG.md
2026-05-28 13:56:00 -04:00
nesquena-hermes
c642c1e438 Merge PR #3069
# Conflicts:
#	CHANGELOG.md
2026-05-28 17:47:34 +00:00
AJV20
60d4b2d990 fix: harden WebUI bugfix sweep 2026-05-28 13:38:50 -04:00
AJV20
9e69db9920 fix: show cron sessions in project filter 2026-05-28 08:10:15 -04:00
Frank Song
9ddf36f510 fix: reset _messagesTruncated flag on new session creation
newSession() did not reset _messagesTruncated or _oldestIdx, unlike
loadSession() which resets both at line 590. When a user switched from
a long session (messages > _INITIAL_MSG_LIMIT) to a new session, the
stale _messagesTruncated=true caused renderMessages() to show the
'Scroll up or click to load older messages' indicator on a fresh
conversation with only 1 message.

Add the same reset that loadSession() already performs so newSession()
starts with clean pagination state.
2026-05-28 12:13:30 +08:00
Dennis Soong
5f901f579a fix: suppress timeout toasts for passive pollers 2026-05-28 11:13:00 +08:00
Florian Krause
8408a3dd22 fix: reattach SSE on session-switch return + close leaked stream connections (#2925)
Squash-merged pr-2925 into stage-batch33. Closes #2924.
2026-05-28 02:48:17 +00:00
Frank Song
8ab9235e00 Preserve server running state in sidebar merge 2026-05-27 12:29:57 +08:00
nesquena-hermes
ad4a4e2d62 Merge pull request #2506
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:38:40 +00:00
nesquena-hermes
e0dfa0c586 Merge pull request #2792 2026-05-27 00:37:48 +00:00
nesquena-hermes
858a250319 Merge pull request #2899 2026-05-27 00:19:20 +00:00
nesquena-hermes
f3fbb49ce4 Merge pull request #2983
# Conflicts:
#	CHANGELOG.md
2026-05-27 00:02:47 +00:00
george-andraws
65cae8f1a5 Improve sidebar chat search highlighting 2026-05-26 14:17:59 -07:00
Frank Song
9db0d6869a fix: keep session switch metadata non-blocking 2026-05-26 16:40:35 +08:00
nesquena-hermes
7c666d8e4d Merge pull request #2913
# Conflicts:
#	CHANGELOG.md
2026-05-25 17:47:51 +00:00
nesquena-hermes
bf28f400ec Merge pull request #2921
# Conflicts:
#	CHANGELOG.md
2026-05-25 17:02:16 +00:00
nesquena-hermes
d86aa6013f Merge pull request #2906 2026-05-25 17:01:47 +00:00
Frank Song
cfca26f2e8 Repaint sidebar after session archive or delete 2026-05-25 16:31:15 +08:00
ai-ag2026
9e74072bf3 fix(chat): resolve stale compression parent routes 2026-05-25 08:54:46 +02:00
ai-ag2026
3009c0bf71 fix(chat): keep compression tip selected in sidebar 2026-05-25 08:28:12 +02:00
ai-ag2026
21655af09b fix(chat): accept session_id URL parameter 2026-05-25 07:59:21 +02:00
ai-ag2026
17233293ac fix(chat): dedupe uploaded-file pending turns 2026-05-25 06:11:22 +02:00
Qi
7bd85405c9 perf(session): cumulative tail-window load for older history
_loadOlderMessages() previously fetched older messages with the legacy
index-cursor page (msg_before=_oldestIdx&msg_limit=30) and prepended
the page to S.messages. After #2716 the backend always runs the full
append-only merge for /api/session?messages=1 — the same merge as a
larger msg_limit on the same call — so we can ask for a larger
authoritative tail window directly instead of stitching pages on the
client.

Behavior

* Default request shape becomes msg_limit=currentLoaded+30. The newly
  exposed head of the response is what the user sees as 'older
  messages'. No new query parameters.
* msg_before remains supported by the backend and is retained in the
  client as a race-fallback path: if the returned tail no longer has
  the currently displayed messages as a suffix (because the session
  appended new messages mid-flight, or merge filtered something), the
  client issues the legacy msg_before page and prepends it instead.
  This preserves correctness under concurrent appends.
* Suffix-continuity uses the existing _sameTranscriptMessage helper,
  which tolerates timestamp drift and content-array reshapes.
* Existing race guards (loadingSessionId, S.session.session_id, and
  the _messagesGeneration snapshot from #1937) are reapplied after
  the fallback await.

Tests

Updated four static-string assertions in the existing scroll/viewport
tests to track the new mutation site (S.messages = nextMessages) and
the new msg_limit=requestedLimit shape, while still asserting that
msg_before remains in the body for the race-fallback path.

  pytest -q
    tests/test_older_history_viewport_preservation.py
    tests/test_parallel_session_switch.py
    tests/test_issue1937_endless_scroll_jumpstart_race.py
    tests/test_session_tail_payload.py
  -> 52 passed
  node --check static/sessions.js -> ok

Notes

Originally part of PR #2835. That PR was closed because of an
architectural conflict with #2716 on a different file (api/models.py
metadata-only path). #2716 left static/sessions.js untouched — this
change applies cleanly on post-#2716 master with no rebase work.
2026-05-25 01:01:45 +00:00
Roberto Villegas
ef5eafcceb
fix(cursor-acp): route slash models and honor picker on new chat
Ensure cursor/composer IDs always resolve via @cursor-acp:, carry the
visible picker selection into POST /api/session/new, persist model
changes before a session exists, and evict cached agents on model switch.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 18:42:20 -06:00
ai-ag2026
8a2f11c770 fix(chat): log sanitized client sse diagnostics
(cherry picked from commit 749ca6e18c5e307fbf7e7fb5fffce97249545017)
2026-05-25 02:06:42 +02:00
hermes-agent
4f20cbd6ca Stage 406: PR #2673 — Add scoped workspace Artifacts tab by @AJV20 (closes #2655)
Cherry-picked via 3-way apply onto stage HEAD.
Resolved workspace.js conflict: kept master's #2716 sessionId-capture
stale-session guard (closure-scoped sessionId check after await), AND
added PR's renderSessionArtifacts() call to refresh the new Artifacts
tab when the file tree updates. Wrapped in typeof check for defense.

Co-authored-by: AJV20 <abdielvc@me.com>
2026-05-24 18:58:37 +00:00
hermes-agent
2419b3a0a2 Stage 404: PR #2830 — fix(sessions): keep pin state authoritative by @franksong2702 (closes #2821)
Agent reviewer 'LGTM. Ship it.'
- Bug A fix: _session_field helper handles dict-vs-object snapshot in pin-limit check
- Bug B fix: removed stale client-side pinLimitReached short-circuit
- Bug C recovery: renderSessionList() on pin/unpin failure refreshes from server

Co-authored-by: franksong2702 <146128127+franksong2702@users.noreply.github.com>
2026-05-24 18:08:42 +00:00
hermes-agent
9d95ba0b92 Stage 404: PR #2716 — Performance optimizations by @dobby-d-elf
nesquena APPROVED 2026-05-22. Cherry-picked onto post-v0.51.127
master via 3-way apply. Resolved api/routes.py conflict: master had
the inline correctness fix from the deep-review iteration; PR
refactors it into _metadata_only_message_summary() helper. Took the
helper AND added profile= threading (post-#2827 master adds
profile-aware state.db reads). Kept master's pre-existing
test_api_session_reload_drops_stale_cached_user_tail_after_saved_assistant
alongside the PR's new test_metadata_fast_path_matches_reconciliation_for_restamped_replays.

Co-authored-by: dobby-d-elf <dobby.the.agent@gmail.com>
2026-05-24 18:08:41 +00:00
ai-ag2026
39242c586c fix: clear stale inflight UI state (closes #2795, squashed from 5 commits)
Cherry-pick of PR #2796 by @ai-ag2026, squashed from 5 author commits onto current master:
- dcee0563 fix: drop stale optimistic sidebar rows
- 3a73400d fix: clear stale busy state before send
- 46c3b902 fix: preserve server idle rows during optimistic merge
- de51d271 fix: let chat start survive pre-start UI errors
- d2f5c906 fix: hide nonfatal pre-start send warnings

Authorship preserved via --author. Code-only squash (no CHANGELOG).
2026-05-24 04:08:25 +00:00
Harlan Zhou
21481e85fd fix(ui): recover from stale /session/{id} on boot-time 404 2026-05-24 03:03:31 +00:00
Frank Song
53f294dc8d Fix composer model picker opening lag 2026-05-22 16:58:55 +00:00
ai-ag2026
6bcc9689aa fix(chat): keep new session model authoritative 2026-05-22 16:50:17 +00:00
ai-ag2026
af1ee81f06 fix(chat): resolve session model before activating 2026-05-22 16:50:17 +00:00
ai-ag2026
dabe7b0ea5 fix(session): keep conversation actions menu clickable 2026-05-22 12:21:10 +02:00
Hermes Agent
0fae9cbdf1 Stage 400: PR #2723 — fix(chat): dedupe uploaded-file optimistic user turns
Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
2026-05-21 22:59:40 +00:00
Hermes Agent
4f3eb9f7f8 Stage 400: PR #2718 — fix: rename _pinnedSessionsLimit() to _getPinnedSessionsLimit() (follow-up to v0.51.105 #2700, matches sessions.js getter convention)
Co-authored-by: eslicarrillo <eslicarrillo@users.noreply.github.com>
2026-05-21 22:59:37 +00:00
Hermes Agent
905b3eba5e Stage 398: PR #2700 — feat: make pinned session limit configurable (builds on shipped #2614 3-cap)
Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
2026-05-21 17:43:56 +00:00
Hermes Agent
e2338f696f Stage 397: PR #2688 — fix: resync virtualized sidebar after scroll clamp
Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
2026-05-21 17:14:36 +00:00
Hermes Agent
d5dcd60981 Stage 397: PR #2674 — fix: new-chat default model provider sync when model id matches but provider differs
Co-authored-by: AJV20 <AJV20@users.noreply.github.com>
2026-05-21 17:14:34 +00:00
Hermes Agent
3dd2ace4e1 Stage 397: PR #2689 — fix(chat): preserve inflight send state during start race
Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
2026-05-21 17:14:33 +00:00
Hermes Agent
12a92dd50a Stage 397: PR #2671 — fix: SSE reconnect jitter + cron run row inline expansion
Closes #2629
Closes #2661

Co-authored-by: AJV20 <AJV20@users.noreply.github.com>
2026-05-21 17:13:59 +00:00
nesquena-hermes
feb35893b9 Stage 393: PR #2637
# Conflicts:
#	static/sessions.js
2026-05-20 22:24:40 +00:00