From 27bc6bade397da811b0fde48534788699d9371c8 Mon Sep 17 00:00:00 2001 From: HeavyGee <133152184+heavygee@users.noreply.github.com> Date: Wed, 5 Aug 2026 02:16:41 +0100 Subject: [PATCH] fix(web): drop Idle session-list badge (keep working/pending) (#1366) * fix(web): drop Idle session-list badge (keep working/pending) Quiet active rows already read as the default via full opacity vs faded archived; labeling Idle was badge inflation. Pin-in-progress now only surfaces working/pending so the section does not advertise lack-of-state. Fixes #1362 Co-authored-by: Cursor * fix(web): include deliveryMode on abort send-error restore Unblocks web typecheck: RawSendError requires deliveryMode, and the abort-restore path was omitting it (already red on upstream/main CI). Co-authored-by: Cursor --------- Co-authored-by: Cursor --- .../SessionList.directory-action.test.tsx | 52 +++++++++++++++++++ web/src/components/SessionList.tsx | 20 ++++--- web/src/components/SessionRowSummary.tsx | 10 ---- web/src/lib/locales/en.ts | 3 +- web/src/lib/locales/zh-CN.ts | 3 +- web/src/router.tsx | 1 + 6 files changed, 68 insertions(+), 21 deletions(-) diff --git a/web/src/components/SessionList.directory-action.test.tsx b/web/src/components/SessionList.directory-action.test.tsx index bdcc6e3f..7d21d8c2 100644 --- a/web/src/components/SessionList.directory-action.test.tsx +++ b/web/src/components/SessionList.directory-action.test.tsx @@ -460,6 +460,58 @@ describe('SessionList collapse behavior', () => { expect(getProjectPanel().getAttribute('data-open')).toBeNull() }) + it('does not label quiet active sessions as Idle', () => { + const sessions = [ + makeSession({ + id: 'session-quiet', + active: true, + updatedAt: 100, + metadata: { path: '/work/hapi', name: 'Quiet task', flavor: 'codex' }, + }), + ] + render(renderSessionList(sessions, null)) + + expect(screen.getByRole('button', { name: /Quiet task/ })).toBeInTheDocument() + expect(screen.queryByText('Idle')).toBeNull() + expect(screen.queryByTitle('Idle')).toBeNull() + }) + + it('keeps quiet active sessions in directory groups when pin-in-progress is on', () => { + localStorage.setItem('hapi-pin-in-progress-sessions', 'true') + const sessions = [ + makeSession({ + id: 'session-running', + active: true, + thinking: true, + updatedAt: 100, + metadata: { path: '/work/hapi', name: 'Running task', flavor: 'codex' }, + }), + makeSession({ + id: 'session-quiet', + active: true, + updatedAt: 90, + metadata: { path: '/work/hapi', name: 'Quiet task', flavor: 'codex' }, + }), + makeSession({ + id: 'session-pending', + active: true, + pendingRequestsCount: 1, + updatedAt: 80, + metadata: { path: '/work/other', name: 'Pending task', flavor: 'codex' }, + }), + ] + render(renderSessionList(sessions, null)) + + expect(screen.getByTitle('In progress')).toBeInTheDocument() + expect(screen.getByText(/Running \(1\)/)).toBeInTheDocument() + expect(screen.getByText(/pending \(1\)/)).toBeInTheDocument() + expect(screen.queryByText(/Idle \(/)).toBeNull() + // Quiet active stays under its project directory, not an Idle pin bucket. + expect(screen.getByTitle('/work/hapi')).toBeInTheDocument() + expect(screen.getByRole('button', { name: /Quiet task/ })).toBeInTheDocument() + expect(getProjectPanel().getAttribute('data-open')).toBe('true') + }) + it('auto-expands the path again when the selected session changes', async () => { const sessions = [ makeSession({ diff --git a/web/src/components/SessionList.tsx b/web/src/components/SessionList.tsx index 5ddc1bd9..b93ed8e7 100644 --- a/web/src/components/SessionList.tsx +++ b/web/src/components/SessionList.tsx @@ -45,9 +45,18 @@ type SessionGroup = { 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 +/** Active sessions that warrant the optional pinned In progress section. Quiet actives stay in directory groups. */ +function isPinnedInProgressSession(session: SessionSummary): boolean { + if (!session.active) { + return false + } + return session.thinking + || (session.backgroundTaskCount ?? 0) > 0 + || (session.pendingRequestsCount ?? 0) > 0 +} + export type SessionTimeRange = { start: number | null end: number | null @@ -1099,10 +1108,9 @@ export function SessionList(props: { [visibleSessions, activeMachineFilter] ) const runningSessions = useMemo(() => { - const buckets: Record<'working' | 'pending' | 'idle', SessionSummary[]> = { + const buckets: Record<'working' | 'pending', SessionSummary[]> = { working: [], pending: [], - idle: [] } if (!pinInProgressSessions) { return buckets @@ -1115,9 +1123,8 @@ export function SessionList(props: { buckets.working.push(session) } else if ((session.pendingRequestsCount ?? 0) > 0) { buckets.pending.push(session) - } else { - buckets.idle.push(session) } + // Quiet active sessions stay in directory groups (no Idle pin bucket). } const byRecent = (a: SessionSummary, b: SessionSummary) => b.updatedAt - a.updatedAt for (const key of Object.keys(buckets) as Array) { @@ -1127,11 +1134,10 @@ export function SessionList(props: { }, [machineFilteredSessions, pinInProgressSessions]) const runningSessionTotal = runningSessions.working.length + runningSessions.pending.length - + runningSessions.idle.length const groups = useMemo( () => groupSessionsByDirectory( pinInProgressSessions - ? machineFilteredSessions.filter((session) => !session.active) + ? machineFilteredSessions.filter((session) => !isPinnedInProgressSession(session)) : machineFilteredSessions ), [machineFilteredSessions, pinInProgressSessions] diff --git a/web/src/components/SessionRowSummary.tsx b/web/src/components/SessionRowSummary.tsx index 73fcfd6d..c31d9440 100644 --- a/web/src/components/SessionRowSummary.tsx +++ b/web/src/components/SessionRowSummary.tsx @@ -205,16 +205,6 @@ export function SessionRowSummary(props: { {t('session.item.pending')} ) : null} - ) : s.active ? ( - - ) : attention && nestedTooltips && attentionId ? (