Files
hapi/web/src/lib/sessionAttention.ts
T
e040d23371 fix(web): ignore pending requests on archived sessions in the sidebar (#2101)
Archived sessions keep their stale pending requests in agentState. The
sidebar still treated them as live: the collapsed folder preview forced
them visible and trimmed active sessions to make room, so a folder could
look like it had no active sessions. They also kept the permission/input
attention dot and the "Pending N" badge.

Only count pending requests on active sessions for preview pinning,
attention, and the badge. The state itself is unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 15:35:15 +08:00

67 lines
1.8 KiB
TypeScript

import type { SessionSummary } from '@/types/api'
export type SessionAttention =
| { kind: 'permission' }
| { kind: 'input' }
| { kind: 'background' }
| { kind: 'unread' }
/** True when the session has activity newer than the operator's last-seen watermark. */
export function sessionIsUnread(
summary: SessionSummary,
options: { lastSeenAt: number }
): boolean {
return summary.updatedAt > options.lastSeenAt
}
export function classifySessionAttention(
summary: SessionSummary,
options: { selected: boolean; lastSeenAt: number; manualUnreadAt?: number | null }
): SessionAttention | null {
if (options.selected) {
return options.manualUnreadAt === summary.updatedAt
? { kind: 'unread' }
: null
}
if (summary.thinking) {
return null
}
// Requests left on an archived session can no longer be answered.
const pendingRequestKinds = summary.active && Array.isArray(summary.pendingRequestKinds)
? summary.pendingRequestKinds
: []
if (pendingRequestKinds.includes('permission')) {
return { kind: 'permission' }
}
if (pendingRequestKinds.includes('input')) {
return { kind: 'input' }
}
if (summary.active && (summary.backgroundTaskCount ?? 0) > 0) {
return { kind: 'background' }
}
if (sessionIsUnread(summary, { lastSeenAt: options.lastSeenAt })) {
return { kind: 'unread' }
}
return null
}
export function getSessionAttentionLabelKey(attention: SessionAttention): string {
switch (attention.kind) {
case 'permission':
return 'session.item.permission'
case 'input':
return 'session.item.needsInput'
case 'background':
return 'session.item.background'
case 'unread':
return 'session.item.newActivity'
}
}