- Shipped
- August 26, 2026 at 3:39 AM UTC
- Author
- kamo
- Commit
- 9d52f8d
AI sessions live in AIService and are not MediaSessions, so this bucket gets its own loader in front of the /api/media/sessions/chat fetch the other four share, then adapts each session into the same Row shape rather than a second renderer — the list, its search, its avatars and its unread chip are one surface, and a second one would drift from the first within a release. Unread comes through the ai: namespace the hexhead badges read (getUnread, not conversationKeyForWindow — a chats-list row is not a tool window), so a row and its minimized window can never disagree about the number. Three gaps beyond the plan's own brief, caught before they shipped quietly: bucketOf() never routed sessionType 'AI' anywhere, so every AI row resolved to 'teamMembers' and the AI tab would have rendered permanently empty; the row's own title never read row.title, so every AI conversation would have shown as "Empty chat"; and 'ai' was missing from ALL_BUCKETS, so the per-member sub-tab preference would silently refuse to restore it after a switch. The brief's own unreadFor() example is also not used as written — replacing the existing unread computation with it wholesale would have zeroed every SOCIAL row's badge (never in the live map, unlike CHAT/SUPPORT) and flashed every row to zero before the live snapshot loads; the AI branch is folded into the existing computation instead, preserving both.