@@ -64,6 +64,9 @@ export function DashboardAgent({
6464 // wake the user has already been shown (and maybe dismissed) must not come
6565 // back every 60s while the chat stays unread.
6666 const toastedWakes = useRef ( new Set < string > ( ) ) ;
67+ // The chat currently on screen (panel open). A wake there streams into the
68+ // visible transcript, so it toasts but must not light the dot.
69+ const visibleChat = useRef < string | null > ( null ) ;
6770 // The side panel is the default; someone who last worked fullscreen gets
6871 // fullscreen back. Read lazily so SSR always renders the side panel.
6972 const [ fullscreen , setFullscreen ] = useState ( readAgentFullscreen ) ;
@@ -116,6 +119,8 @@ export function DashboardAgent({
116119 // Closing drops both pending requests: the panel unmounts, so a stale one
117120 // would re-apply on the next open instead of restoring the last chat.
118121 if ( ! next ) {
122+ // No chat is on screen any more — the dot counts every unread wake again.
123+ visibleChat . current = null ;
119124 setRequestedMessage ( undefined ) ;
120125 setOpenChatRequest ( undefined ) ;
121126 // An abandoned card leaves no trace (§2.2) — including no pending request
@@ -158,7 +163,10 @@ export function DashboardAgent({
158163 if ( ! res . ok ) return ;
159164 const data = ( await res . json ( ) ) as { unreadWakes ?: number ; wakes ?: WatchWake [ ] } ;
160165 if ( cancelled ) return ;
161- setUnreadWakes ( data . unreadWakes ?? 0 ) ;
166+ const wakesInView = ( data . wakes ?? [ ] ) . filter (
167+ ( wake ) => wake . chatId === visibleChat . current
168+ ) . length ;
169+ setUnreadWakes ( Math . max ( 0 , ( data . unreadWakes ?? 0 ) - wakesInView ) ) ;
162170
163171 const fresh = ( data . wakes ?? [ ] ) . filter ( ( wake ) => ! toastedWakes . current . has ( wake . watchId ) ) ;
164172 for ( const wake of fresh ) toastedWakes . current . add ( wake . watchId ) ;
@@ -191,6 +199,7 @@ export function DashboardAgent({
191199 // persists the read marker for the chat that's actually visible.
192200 const markChatRead = useCallback (
193201 async ( chatId : string ) => {
202+ visibleChat . current = chatId ;
194203 setUnreadWakes ( 0 ) ;
195204 const body = new FormData ( ) ;
196205 body . set ( "intent" , "read" ) ;
0 commit comments