stage #4688 (franksong2702): running-first session ordering in sidebar (#4699)

Overlays live pending_started_at/updated_at/last_message_at onto cached /api/sessions rows
(when newer), sorts active/running sessions first then by freshest effective timestamp, applies
the same running-first order in the frontend sidebar renderer, and groups date buckets with the
same runtime-aware timestamp (no stale header on resumed running sessions). routes.py +
sessions.js + 81-line test. Composes with #4680 cache-freeze + #4597 (98 session-list tests pass).

Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
Co-authored-by: franksong2702 <franksong2702@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-06-22 03:52:19 -07:00
1 parent 148222b40a
commit c5bb1fcaa0
4 files changed
+154 -2

No files matched your search

+47
View File
@@ -1844,12 +1844,59 @@ def _session_list_cache_overlay_runtime_rows(rows: list[dict]) -> list[dict]:
item["has_pending_user_message"] = bool(
getattr(live, "pending_user_message", None)
)
for key in ("pending_started_at", "updated_at", "last_message_at"):
current = _session_list_row_numeric_value(item.get(key))
raw_live_value = getattr(live, key, None)
live_value = _session_list_row_numeric_value(raw_live_value)
if live_value > current:
item[key] = raw_live_value
stream_id = item.get("active_stream_id")
item["is_streaming"] = bool(stream_id and stream_id in active_stream_ids)
overlaid.append(item)
overlaid.sort(key=_session_list_runtime_sort_key, reverse=True)
return overlaid
def _session_list_row_numeric_value(value) -> float:
try:
numeric = float(value or 0)
except (TypeError, ValueError):
return 0.0
return numeric if numeric > 0 else 0.0
def _session_list_row_timestamp(row: dict) -> float:
if not isinstance(row, dict):
return 0.0
# Match the frontend `_sessionSortTimestampMs` semantics exactly (#4688 review):
# the idle base is the FIRST truthy of last_message_at -> updated_at -> created_at
# (NOT a flat max over all of them — a renamed/metadata-touched idle chat bumps
# updated_at without new messages and must not outrank a newer chatted session),
# then pending_started_at is overlaid only as the runtime promotion.
base = 0.0
for key in ("last_message_at", "updated_at", "created_at"):
base = _session_list_row_numeric_value(row.get(key))
if base > 0:
break
pending = _session_list_row_numeric_value(row.get("pending_started_at"))
return max(base, pending)
def _session_list_row_is_runtime_active(row: dict) -> bool:
if not isinstance(row, dict):
return False
if row.get("is_streaming"):
return True
return bool(row.get("active_stream_id") and row.get("has_pending_user_message"))
def _session_list_runtime_sort_key(row: dict) -> tuple[int, float]:
return (
1 if _session_list_row_is_runtime_active(row) else 0,
_session_list_row_timestamp(row),
)
def _session_list_cache_claim_rebuild(key: tuple) -> tuple[threading.Event, bool]:
with _SESSIONS_CACHE_LOCK:
current = _SESSIONS_CACHE_INFLIGHT.get(key)