1- import { TextAttributes } from '@opentui/core'
21import { pluralize } from '@codebuff/common/util/string'
2+ import { TextAttributes } from '@opentui/core'
33import React , { memo , useCallback , useMemo , type ReactNode } from 'react'
44
5- import {
6- shouldRenderAsSimpleText ,
7- isImplementorAgent ,
8- getImplementorDisplayName ,
9- } from '../utils/constants'
105import { AgentBranchItem } from './agent-branch-item'
116import { ElapsedTimer } from './elapsed-timer'
127import { FeedbackIconButton } from './feedback-icon-button'
138import { useTheme } from '../hooks/use-theme'
149import { useWhyDidYouUpdateById } from '../hooks/use-why-did-you-update'
15- import { isTextBlock , isToolBlock } from '../types/chat'
16- import { type MarkdownPalette } from '../utils/markdown-renderer'
1710import {
1811 useFeedbackStore ,
1912 selectIsFeedbackOpenForMessage ,
2013 selectHasSubmittedFeedback ,
2114 selectMessageFeedbackCategory ,
2215} from '../state/feedback-store'
16+ import { isTextBlock , isToolBlock } from '../types/chat'
17+ import { shouldRenderAsSimpleText } from '../utils/constants'
18+ import {
19+ isImplementorAgent ,
20+ getImplementorDisplayName ,
21+ getImplementorIndex ,
22+ } from '../utils/implementor-helpers'
23+ import { type MarkdownPalette } from '../utils/markdown-renderer'
24+ import { AgentListBranch } from './blocks/agent-list-branch'
25+ import { ContentWithMarkdown } from './blocks/content-with-markdown'
26+ import { ThinkingBlock } from './blocks/thinking-block'
27+ import { ToolBranch } from './blocks/tool-branch'
28+ import { PlanBox } from './renderers/plan-box'
2329
2430import type {
2531 ContentBlock ,
@@ -28,12 +34,6 @@ import type {
2834 AgentContentBlock ,
2935} from '../types/chat'
3036import type { ThemeColor } from '../types/theme-system'
31- import { ThinkingBlock } from './blocks/thinking-block'
32- import { ContentWithMarkdown } from './blocks/content-with-markdown'
33- import { ToolBranch } from './blocks/tool-branch'
34- import { PlanBox } from './renderers/plan-box'
35- import { AgentListBranch } from './blocks/agent-list-branch'
36- import { BULLET_CHAR } from '../utils/strings'
3737
3838interface MessageBlockProps {
3939 messageId : string
@@ -378,6 +378,24 @@ const AgentBody = memo(
378378 const nestedBlocks = agentBlock . blocks ?? [ ]
379379 const nodes : React . ReactNode [ ] = [ ]
380380
381+ // Pre-calculate numbering for all implementor siblings
382+ const implementorIndexMap = new Map < string , number > ( )
383+ nestedBlocks
384+ . filter (
385+ ( block ) : block is AgentContentBlock =>
386+ block . type === 'agent' && isImplementorAgent ( block . agentType ) ,
387+ )
388+ . forEach ( ( block ) => {
389+ const index = getImplementorIndex (
390+ block . agentId ,
391+ block . agentType ,
392+ nestedBlocks ,
393+ )
394+ if ( index !== undefined ) {
395+ implementorIndexMap . set ( block . agentId , index )
396+ }
397+ } )
398+
381399 const getAgentMarkdownOptions = useCallback (
382400 ( indent : number ) => {
383401 const indentationOffset = indent * 2
@@ -537,6 +555,7 @@ const AgentBody = memo(
537555
538556 case 'agent' : {
539557 const agentBlock = nestedBlock as AgentContentBlock
558+ const numbering = implementorIndexMap . get ( agentBlock . agentId )
540559 nodes . push (
541560 < AgentBranchWrapper
542561 key = { `${ keyPrefix } -agent-${ nestedIdx } ` }
@@ -549,6 +568,7 @@ const AgentBody = memo(
549568 onToggleCollapsed = { onToggleCollapsed }
550569 onBuildFast = { onBuildFast }
551570 onBuildMax = { onBuildMax }
571+ implementorIndex = { numbering }
552572 /> ,
553573 )
554574 nestedIdx ++
@@ -571,6 +591,7 @@ interface AgentBranchWrapperProps {
571591 onToggleCollapsed : ( id : string ) => void
572592 onBuildFast : ( ) => void
573593 onBuildMax : ( ) => void
594+ implementorIndex ?: number
574595}
575596
576597const AgentBranchWrapper = memo (
@@ -584,6 +605,7 @@ const AgentBranchWrapper = memo(
584605 onToggleCollapsed,
585606 onBuildFast,
586607 onBuildMax,
608+ implementorIndex,
587609 } : AgentBranchWrapperProps ) => {
588610 const theme = useTheme ( )
589611
@@ -627,7 +649,10 @@ const AgentBranchWrapper = memo(
627649 streamingAgents . has ( agentBlock . agentId )
628650 const isComplete = agentBlock . status === 'complete'
629651 const isFailed = agentBlock . status === 'failed'
630- const displayName = getImplementorDisplayName ( agentBlock . agentType )
652+ const displayName = getImplementorDisplayName (
653+ agentBlock . agentType ,
654+ implementorIndex ,
655+ )
631656 const statusIndicator = isStreaming
632657 ? '●'
633658 : isFailed
@@ -799,6 +824,7 @@ interface SingleBlockProps {
799824 onToggleCollapsed : ( id : string ) => void
800825 onBuildFast : ( ) => void
801826 onBuildMax : ( ) => void
827+ implementorIndex ?: number
802828}
803829
804830const SingleBlock = memo (
@@ -817,6 +843,7 @@ const SingleBlock = memo(
817843 onToggleCollapsed,
818844 onBuildFast,
819845 onBuildMax,
846+ implementorIndex,
820847 } : SingleBlockProps ) : ReactNode => {
821848 const theme = useTheme ( )
822849 const codeBlockWidth = Math . max ( 10 , availableWidth - 8 )
@@ -913,6 +940,7 @@ const SingleBlock = memo(
913940 onToggleCollapsed = { onToggleCollapsed }
914941 onBuildFast = { onBuildFast }
915942 onBuildMax = { onBuildMax }
943+ implementorIndex = { implementorIndex }
916944 />
917945 )
918946 }
@@ -965,6 +993,24 @@ const BlocksRenderer = memo(
965993 onBuildMax,
966994 } : BlocksRendererProps ) => {
967995 const nodes : React . ReactNode [ ] = [ ]
996+
997+ // Pre-calculate numbering for all implementor siblings at the top level
998+ const topLevelImplementorIndexMap = new Map < string , number > ( )
999+ sourceBlocks
1000+ . filter (
1001+ ( block ) : block is AgentContentBlock =>
1002+ block . type === 'agent' && isImplementorAgent ( block . agentType ) ,
1003+ )
1004+ . forEach ( ( block ) => {
1005+ const index = getImplementorIndex (
1006+ block . agentId ,
1007+ block . agentType ,
1008+ sourceBlocks ,
1009+ )
1010+ if ( index !== undefined ) {
1011+ topLevelImplementorIndexMap . set ( block . agentId , index )
1012+ }
1013+ } )
9681014 for ( let i = 0 ; i < sourceBlocks . length ; ) {
9691015 const block = sourceBlocks [ i ]
9701016 // Handle reasoning text blocks
@@ -1045,6 +1091,10 @@ const BlocksRenderer = memo(
10451091 continue
10461092 }
10471093
1094+ const numbering =
1095+ block . type === 'agent'
1096+ ? topLevelImplementorIndexMap . get ( block . agentId )
1097+ : undefined
10481098 nodes . push (
10491099 < SingleBlock
10501100 key = { `${ messageId } -block-${ i } ` }
@@ -1062,6 +1112,7 @@ const BlocksRenderer = memo(
10621112 onToggleCollapsed = { onToggleCollapsed }
10631113 onBuildFast = { onBuildFast }
10641114 onBuildMax = { onBuildMax }
1115+ implementorIndex = { numbering }
10651116 /> ,
10661117 )
10671118 i ++
0 commit comments