mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-07 01:21:37 +00:00
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>
67 lines
1.8 KiB
TypeScript
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'
|
|
}
|
|
}
|