@@ -73,6 +73,7 @@ type MessageRowProps = {
7373
7474type ReasoningRowProps = {
7575 item : Extract < ConversationItem , { kind : "reasoning" } > ;
76+ parsed : ReturnType < typeof parseReasoning > ;
7677 isExpanded : boolean ;
7778 onToggle : ( id : string ) => void ;
7879 onOpenFileLink ?: ( path : string ) => void ;
@@ -124,6 +125,9 @@ type MessageListEntry =
124125 | { kind : "item" ; item : ConversationItem }
125126 | { kind : "toolGroup" ; group : ToolGroup } ;
126127
128+ const SCROLL_THRESHOLD_PX = 120 ;
129+ const MAX_COMMAND_OUTPUT_LINES = 200 ;
130+
127131function basename ( path : string ) {
128132 if ( ! path ) {
129133 return "" ;
@@ -225,23 +229,6 @@ function parseReasoning(item: Extract<ConversationItem, { kind: "reasoning" }>)
225229 } ;
226230}
227231
228- function reasoningWorkingLabel ( items : ConversationItem [ ] ) {
229- for ( let index = items . length - 1 ; index >= 0 ; index -= 1 ) {
230- const item = items [ index ] ;
231- if ( item . kind === "message" ) {
232- break ;
233- }
234- if ( item . kind !== "reasoning" ) {
235- continue ;
236- }
237- const parsed = parseReasoning ( item ) ;
238- if ( parsed . workingLabel ) {
239- return parsed . workingLabel ;
240- }
241- }
242- return null ;
243- }
244-
245232function normalizeMessageImageSrc ( path : string ) {
246233 if ( ! path ) {
247234 return "" ;
@@ -743,12 +730,13 @@ const MessageRow = memo(function MessageRow({
743730
744731const ReasoningRow = memo ( function ReasoningRow ( {
745732 item,
733+ parsed,
746734 isExpanded,
747735 onToggle,
748736 onOpenFileLink,
749737 onOpenFileLinkMenu,
750738} : ReasoningRowProps ) {
751- const { summaryTitle, bodyText, hasBody } = parseReasoning ( item ) ;
739+ const { summaryTitle, bodyText, hasBody } = parsed ;
752740 const reasoningTone : StatusTone = hasBody ? "completed" : "processing" ;
753741 return (
754742 < div className = "tool-inline reasoning-inline" >
@@ -1004,12 +992,11 @@ const CommandOutput = memo(function CommandOutput({ output }: CommandOutputProps
1004992 }
1005993 return output . split ( / \r ? \n / ) ;
1006994 } , [ output ] ) ;
1007- const maxStoredLines = 200 ;
1008995 const lineWindow = useMemo ( ( ) => {
1009- if ( lines . length <= maxStoredLines ) {
996+ if ( lines . length <= MAX_COMMAND_OUTPUT_LINES ) {
1010997 return { offset : 0 , lines } ;
1011998 }
1012- const startIndex = lines . length - maxStoredLines ;
999+ const startIndex = lines . length - MAX_COMMAND_OUTPUT_LINES ;
10131000 return { offset : startIndex , lines : lines . slice ( startIndex ) } ;
10141001 } , [ lines ] ) ;
10151002
@@ -1105,7 +1092,6 @@ export const Messages = memo(function Messages({
11051092 userInputRequests = [ ] ,
11061093 onUserInputSubmit,
11071094} : MessagesProps ) {
1108- const SCROLL_THRESHOLD_PX = 120 ;
11091095 const bottomRef = useRef < HTMLDivElement | null > ( null ) ;
11101096 const containerRef = useRef < HTMLDivElement | null > ( null ) ;
11111097 const autoScrollRef = useRef ( true ) ;
@@ -1133,7 +1119,7 @@ export const Messages = memo(function Messages({
11331119 const isNearBottom = useCallback (
11341120 ( node : HTMLDivElement ) =>
11351121 node . scrollHeight - node . scrollTop - node . clientHeight <= SCROLL_THRESHOLD_PX ,
1136- [ SCROLL_THRESHOLD_PX ] ,
1122+ [ ] ,
11371123 ) ;
11381124
11391125 const updateAutoScroll = ( ) => {
@@ -1183,17 +1169,42 @@ export const Messages = memo(function Messages({
11831169 } ) ;
11841170 } , [ ] ) ;
11851171
1186- const latestReasoningLabel = useMemo ( ( ) => reasoningWorkingLabel ( items ) , [ items ] ) ;
1172+ const reasoningMetaById = useMemo ( ( ) => {
1173+ const meta = new Map < string , ReturnType < typeof parseReasoning > > ( ) ;
1174+ items . forEach ( ( item ) => {
1175+ if ( item . kind === "reasoning" ) {
1176+ meta . set ( item . id , parseReasoning ( item ) ) ;
1177+ }
1178+ } ) ;
1179+ return meta ;
1180+ } , [ items ] ) ;
1181+
1182+ const latestReasoningLabel = useMemo ( ( ) => {
1183+ for ( let index = items . length - 1 ; index >= 0 ; index -= 1 ) {
1184+ const item = items [ index ] ;
1185+ if ( item . kind === "message" ) {
1186+ break ;
1187+ }
1188+ if ( item . kind !== "reasoning" ) {
1189+ continue ;
1190+ }
1191+ const parsed = reasoningMetaById . get ( item . id ) ;
1192+ if ( parsed ?. workingLabel ) {
1193+ return parsed . workingLabel ;
1194+ }
1195+ }
1196+ return null ;
1197+ } , [ items , reasoningMetaById ] ) ;
11871198
11881199 const visibleItems = useMemo (
11891200 ( ) =>
11901201 items . filter ( ( item ) => {
11911202 if ( item . kind !== "reasoning" ) {
11921203 return true ;
11931204 }
1194- return parseReasoning ( item ) . hasBody ;
1205+ return reasoningMetaById . get ( item . id ) ? .hasBody ?? false ;
11951206 } ) ,
1196- [ items ] ,
1207+ [ items , reasoningMetaById ] ,
11971208 ) ;
11981209
11991210 useEffect ( ( ) => {
@@ -1281,10 +1292,12 @@ export const Messages = memo(function Messages({
12811292 }
12821293 if ( item . kind === "reasoning" ) {
12831294 const isExpanded = expandedItems . has ( item . id ) ;
1295+ const parsed = reasoningMetaById . get ( item . id ) ?? parseReasoning ( item ) ;
12841296 return (
12851297 < ReasoningRow
12861298 key = { item . id }
12871299 item = { item }
1300+ parsed = { parsed }
12881301 isExpanded = { isExpanded }
12891302 onToggle = { toggleExpanded }
12901303 onOpenFileLink = { openFileLink }
0 commit comments