@@ -177,6 +177,27 @@ function toolStatusTone(
177177 return "processing" ;
178178}
179179
180+ function scrollKeyForItems ( items : ConversationItem [ ] ) {
181+ if ( ! items . length ) {
182+ return "empty" ;
183+ }
184+ const last = items [ items . length - 1 ] ;
185+ switch ( last . kind ) {
186+ case "message" :
187+ return `${ last . id } -${ last . text . length } ` ;
188+ case "reasoning" :
189+ return `${ last . id } -${ last . summary . length } -${ last . content . length } ` ;
190+ case "tool" :
191+ return `${ last . id } -${ last . status ?? "" } -${ last . output ?. length ?? 0 } ` ;
192+ case "diff" :
193+ return `${ last . id } -${ last . status ?? "" } -${ last . diff . length } ` ;
194+ case "review" :
195+ return `${ last . id } -${ last . state } -${ last . text . length } ` ;
196+ default :
197+ return last . id ;
198+ }
199+ }
200+
180201export function Messages ( {
181202 items,
182203 isThinking,
@@ -186,6 +207,7 @@ export function Messages({
186207 const bottomRef = useRef < HTMLDivElement | null > ( null ) ;
187208 const [ expandedItems , setExpandedItems ] = useState < Set < string > > ( new Set ( ) ) ;
188209 const [ elapsedMs , setElapsedMs ] = useState ( 0 ) ;
210+ const scrollKey = scrollKeyForItems ( items ) ;
189211 const toggleExpanded = ( id : string ) => {
190212 setExpandedItems ( ( prev ) => {
191213 const next = new Set ( prev ) ;
@@ -220,7 +242,7 @@ export function Messages({
220242 window . cancelAnimationFrame ( raf2 ) ;
221243 }
222244 } ;
223- } , [ items . length , isThinking ] ) ;
245+ } , [ scrollKey , isThinking ] ) ;
224246
225247 useEffect ( ( ) => {
226248 if ( ! isThinking || ! processingStartedAt ) {
0 commit comments