diff --git a/web/src/components/SessionList.tsx b/web/src/components/SessionList.tsx index d637745d..f38e4aaf 100644 --- a/web/src/components/SessionList.tsx +++ b/web/src/components/SessionList.tsx @@ -41,6 +41,12 @@ type SessionGroup = { hasActiveSession: boolean } +const RUNNING_BUCKETS = [ + { key: 'working', labelKey: 'session.item.running', colorClass: 'text-[var(--app-badge-success-text)]', pulse: true }, + { key: 'pending', labelKey: 'session.item.pending', colorClass: 'text-[var(--app-badge-warning-text)]', pulse: true }, + { key: 'idle', labelKey: 'session.item.idle', colorClass: 'text-[var(--app-hint)]', pulse: false }, +] as const + export type SessionTimeRange = { start: number | null end: number | null @@ -1072,12 +1078,33 @@ export function SessionList(props: { : visibleSessions.filter(session => (session.metadata?.machineId ?? UNKNOWN_MACHINE_ID) === activeMachineFilter), [visibleSessions, activeMachineFilter] ) - const runningSessions = useMemo( - () => machineFilteredSessions - .filter((session) => session.active) - .sort((a, b) => b.updatedAt - a.updatedAt), - [machineFilteredSessions] - ) + const runningSessions = useMemo(() => { + const buckets: Record<'working' | 'pending' | 'idle', SessionSummary[]> = { + working: [], + pending: [], + idle: [] + } + for (const session of machineFilteredSessions) { + if (!session.active) { + continue + } + if (session.thinking || (session.backgroundTaskCount ?? 0) > 0) { + buckets.working.push(session) + } else if ((session.pendingRequestsCount ?? 0) > 0) { + buckets.pending.push(session) + } else { + buckets.idle.push(session) + } + } + const byRecent = (a: SessionSummary, b: SessionSummary) => b.updatedAt - a.updatedAt + for (const key of Object.keys(buckets) as Array) { + buckets[key].sort(byRecent) + } + return buckets + }, [machineFilteredSessions]) + const runningSessionTotal = runningSessions.working.length + + runningSessions.pending.length + + runningSessions.idle.length const groups = useMemo( () => groupSessionsByDirectory(machineFilteredSessions.filter((session) => !session.active)), [machineFilteredSessions] @@ -1417,13 +1444,13 @@ export function SessionList(props: { /> ) : null} - {props.sessions.length > 0 && (isFiltering || activeMachineFilter !== null) && groups.length === 0 && runningSessions.length === 0 ? ( + {props.sessions.length > 0 && (isFiltering || activeMachineFilter !== null) && groups.length === 0 && runningSessionTotal === 0 ? (
{t('sessions.search.noResults')}
) : null} - {runningSessions.length > 0 ? ( + {runningSessionTotal > 0 ? (
- ({runningSessions.length}) + ({runningSessionTotal})
- {runningSessions.map((s) => ( - - ))} + {RUNNING_BUCKETS.map((bucket) => { + const sessions = runningSessions[bucket.key] + if (sessions.length === 0) { + return null + } + return ( +
+
+
+ {sessions.map((s) => ( + + ))} +
+ ) + })}
diff --git a/web/src/components/SessionRowSummary.tsx b/web/src/components/SessionRowSummary.tsx index cbb46ad1..73fcfd6d 100644 --- a/web/src/components/SessionRowSummary.tsx +++ b/web/src/components/SessionRowSummary.tsx @@ -185,7 +185,7 @@ export function SessionRowSummary(props: { title={attentionLabel ?? undefined} aria-label={attentionLabel ?? undefined} /> - ) : s.active ? ( + ) : s.active && (s.backgroundTaskCount ?? 0) > 0 ? ( {t('session.item.running')} ) : null} + ) : s.active && (s.pendingRequestsCount ?? 0) > 0 ? ( + + + ) : s.active ? ( + + ) : attention && nestedTooltips && attentionId ? (