openclaw - 💡(How to fix) Fix Control UI sessions list: manual refresh does full reload instead of incremental/delta update

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Fix Action

Fix / Workaround

  1. Event stream as source of truth: When a sessions.changed event arrives, applySessionsChangedEvent() already patches individual rows without a full reload. This should keep the list live most of the time, reducing the need for manual refreshes.
RAW_BUFFERClick to expand / collapse

Problem

In the Control UI sessions view (/sessions), clicking the Refresh button performs a full reload of all sessions via sessions.list — it discards the entire in-memory result set and re-fetches everything from the backend. This is slow when there are many sessions (especially archived ones) and disrupts the user experience (table flickers, expanded checkpoint details collapse, scroll position resets).

There is already a working incremental update mechanism via applySessionsChangedEvent() in ui/src/ui/controllers/sessions.ts that processes sessions.changed events (insert/update/delete individual rows). However, the manual Refresh button does not leverage this.

Current behavior

  1. User clicks Refresh (or navigates to the sessions tab)
  2. loadSessions()client.request("sessions.list", params) → full SQL query → returns ALL matching sessions
  3. state.sessionsResult is completely replaced
  4. Expansions, selections, and scroll position are lost
  5. If no limit filter is set (default = 0), it loads every session

See: ui/src/ui/views/sessions.ts line ~518 (Refresh button), ui/src/ui/controllers/sessions.ts line ~490 (loadSessions).

Expected behavior

The sessions view should stay fresh through event-driven incremental updates as the primary mechanism, with full reload as a fallback only:

  1. Event stream as source of truth: When a sessions.changed event arrives, applySessionsChangedEvent() already patches individual rows without a full reload. This should keep the list live most of the time, reducing the need for manual refreshes.

  2. Refresh button should be delta/diff aware: Instead of re-fetching everything, either:

    • Option A (best): Add a since / updatedSince parameter to sessions.list so the backend only returns sessions changed after a given timestamp. Combine with current state on the client side for a seamless merge.
    • Option B (medium): Let the Refresh button simply ensure the event stream is active (reconnect if disconnected) and show a short "syncing" indicator — no full reload needed when the stream is live.
    • Option C (minimum): Keep the full reload but preserve expanded/details state, selection, and scroll position across the reload, and add a progress indication.
  3. Default limit should be non-zero: Loading all sessions by default is rarely useful. A sensible default (e.g., 50 or 100) should apply even when the user hasn't set a manual limit filter.

Technical notes

  • The event-driven incremental update applySessionsChangedEvent() already handles insert/update/delete correctly and preserves the sort order (by updatedAt). It lives alongside loadSessions() but is only triggered by live gateway events, not by the manual Refresh button.
  • The loadSessionsOnce function already supports overrides.append for "Load More" pagination (added in 2026.5.22). The Refresh button path (overrides?.append !== true) still does a full replacement.
  • SESSION_EVENT_ROW_FIELDS covers all mutable session fields, so event-based updates are already comprehensive.

Suggested approach

  1. For the short term (small UX win): Preserve expanded checkpoint detail keys and selected session keys across loadSessions full reloads.
  2. For the medium term: Add a since query parameter to the sessions.list gateway handler (server-side), and pass it from the client on refresh.
  3. For the long term: Make the event stream the primary data source and treat full reloads as a diagnostic fallback (e.g., only on explicit "reconnect" or connection-loss recovery).

Related

  • PR #85237 added search and Load More pagination (2026.5.22)
  • ui/src/ui/controllers/sessions.tsapplySessionsChangedEvent, loadSessions
  • ui/src/ui/views/sessions.ts — Refresh button

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The sessions view should stay fresh through event-driven incremental updates as the primary mechanism, with full reload as a fallback only:

  1. Event stream as source of truth: When a sessions.changed event arrives, applySessionsChangedEvent() already patches individual rows without a full reload. This should keep the list live most of the time, reducing the need for manual refreshes.

  2. Refresh button should be delta/diff aware: Instead of re-fetching everything, either:

    • Option A (best): Add a since / updatedSince parameter to sessions.list so the backend only returns sessions changed after a given timestamp. Combine with current state on the client side for a seamless merge.
    • Option B (medium): Let the Refresh button simply ensure the event stream is active (reconnect if disconnected) and show a short "syncing" indicator — no full reload needed when the stream is live.
    • Option C (minimum): Keep the full reload but preserve expanded/details state, selection, and scroll position across the reload, and add a progress indication.
  3. Default limit should be non-zero: Loading all sessions by default is rarely useful. A sensible default (e.g., 50 or 100) should apply even when the user hasn't set a manual limit filter.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING