feat(desktop): split cron sessions into their own sidebar section
Scheduler sessions (source=cron) were listed in recents, where their `[IMPORTANT: …]` first-message previews spammed the list — and because cron runs are always newest, a burst of them consumed the whole recents page budget and starved real conversations (sidebar showed 0 sessions). Recents and cron jobs are now two independent lists: - Backend: /api/sessions + /api/profiles/sessions accept source / exclude_sources; session_count gains exclude_sources. Recents query excludes cron; the cron section queries source=cron. - Desktop: separate $cronSessions store + refreshCronSessions fetch, a collapsed (persisted) "Cron jobs" section below Sessions that only renders when cron sessions exist, with its own bounded scroller.
This commit is contained in:
@@ -1574,6 +1574,8 @@ async def get_sessions(
|
||||
min_messages: int = 0,
|
||||
archived: str = "exclude",
|
||||
order: str = "created",
|
||||
source: str = None,
|
||||
exclude_sources: str = None,
|
||||
):
|
||||
"""List sessions.
|
||||
|
||||
@@ -1604,7 +1606,14 @@ async def get_sessions(
|
||||
min_message_count = max(0, min_messages)
|
||||
archived_only = archived == "only"
|
||||
include_archived = archived == "include"
|
||||
# Optional source scoping: ``source`` includes a single class,
|
||||
# ``exclude_sources`` (comma-separated) drops classes. The desktop
|
||||
# uses these to split recents (exclude=cron) from the cron-jobs
|
||||
# section (source=cron) into two independent lists.
|
||||
exclude_list = [s for s in (exclude_sources or "").split(",") if s.strip()]
|
||||
sessions = db.list_sessions_rich(
|
||||
source=source or None,
|
||||
exclude_sources=exclude_list or None,
|
||||
limit=limit,
|
||||
offset=offset,
|
||||
min_message_count=min_message_count,
|
||||
@@ -1613,6 +1622,8 @@ async def get_sessions(
|
||||
order_by_last_active=order == "recent",
|
||||
)
|
||||
total = db.session_count(
|
||||
source=source or None,
|
||||
exclude_sources=exclude_list or None,
|
||||
min_message_count=min_message_count,
|
||||
include_archived=include_archived,
|
||||
archived_only=archived_only,
|
||||
@@ -1642,6 +1653,8 @@ async def get_profiles_sessions(
|
||||
archived: str = "exclude",
|
||||
order: str = "recent",
|
||||
profile: str = "all",
|
||||
source: str = None,
|
||||
exclude_sources: str = None,
|
||||
):
|
||||
"""Unified, read-only session list aggregated across ALL profiles.
|
||||
|
||||
@@ -1677,6 +1690,11 @@ async def get_profiles_sessions(
|
||||
min_message_count = max(0, min_messages)
|
||||
archived_only = archived == "only"
|
||||
include_archived = archived == "include"
|
||||
# Source scoping (see /api/sessions): recents pass exclude_sources=cron,
|
||||
# the cron-jobs section passes source=cron — two independent lists so
|
||||
# newest cron sessions can't starve the recents page.
|
||||
source_filter = source or None
|
||||
exclude_list = [s for s in (exclude_sources or "").split(",") if s.strip()]
|
||||
# Over-fetch per profile so the merged+sorted window is correct for the
|
||||
# requested page. Capped so a huge profile can't blow up the response.
|
||||
per_profile = min(max(limit + offset, limit), 500)
|
||||
@@ -1700,6 +1718,8 @@ async def get_profiles_sessions(
|
||||
continue
|
||||
try:
|
||||
rows = db.list_sessions_rich(
|
||||
source=source_filter,
|
||||
exclude_sources=exclude_list or None,
|
||||
limit=per_profile,
|
||||
offset=0,
|
||||
min_message_count=min_message_count,
|
||||
@@ -1708,6 +1728,8 @@ async def get_profiles_sessions(
|
||||
order_by_last_active=order == "recent",
|
||||
)
|
||||
profile_total = db.session_count(
|
||||
source=source_filter,
|
||||
exclude_sources=exclude_list or None,
|
||||
min_message_count=min_message_count,
|
||||
include_archived=include_archived,
|
||||
archived_only=archived_only,
|
||||
|
||||
Reference in New Issue
Block a user