@@ -12,6 +12,7 @@ import {
1212} from 'react'
1313import { cn } from '@sim/emcn'
1414import { PrepareFileEdit , Read as ReadTool } from '@/lib/mothership/generated/tool-catalog-v1'
15+ import type { AgentPlanItem } from '@/lib/mothership/request/types'
1516import { isToolHiddenInUi } from '@/lib/mothership/tools/client/hidden-tools'
1617import { resolveToolDisplay } from '@/lib/mothership/tools/client/store-utils'
1718import { ClientToolCallState } from '@/lib/mothership/tools/client/tool-call-state'
@@ -21,6 +22,7 @@ import {
2122 humanizeToolName ,
2223} from '@/lib/mothership/tools/tool-display'
2324import { useChatSurface } from '@/app/workspace/[workspaceId]/home/components/chat-surface-context'
25+ import { PlanChecklist } from '@/app/workspace/[workspaceId]/home/components/message-content/components/plan-checklist'
2426import type { CredentialSubmissionPayload } from '@/app/workspace/[workspaceId]/home/components/message-content/components/special-tags'
2527import { useCustomBlockOverlayVersion } from '@/blocks/custom/client-overlay'
2628import type { ContentBlock , OptionItem , ToolCallData } from '../../types'
@@ -67,7 +69,17 @@ interface StoppedSegment {
6769 type : 'stopped'
6870}
6971
70- type MessageSegment = TextSegment | AgentGroupSegment | OptionsSegment | StoppedSegment
72+ interface PlanSegment {
73+ type : 'plan'
74+ items : AgentPlanItem [ ]
75+ }
76+
77+ type MessageSegment =
78+ | TextSegment
79+ | AgentGroupSegment
80+ | OptionsSegment
81+ | StoppedSegment
82+ | PlanSegment
7183
7284function getAgentGroupActivityKey ( items : AgentGroupItem [ ] ) : string {
7385 return items
@@ -108,6 +120,9 @@ function getVisibleStreamActivityKey(segments: MessageSegment[]): string {
108120 return `options:${ segment . items . map ( ( item ) => `${ item . id } :${ item . label . length } ` ) . join ( ',' ) } `
109121 }
110122 if ( segment . type === 'stopped' ) return 'stopped'
123+ if ( segment . type === 'plan' ) {
124+ return `plan:${ segment . items . map ( ( item ) => `${ item . status } :${ item . step . length } ` ) . join ( ',' ) } `
125+ }
111126 return [
112127 'agent' ,
113128 segment . id ,
@@ -455,6 +470,12 @@ function parseBlocksWithSpanTree(blocks: ContentBlock[]): MessageSegment[] {
455470 continue
456471 }
457472
473+ if ( block . type === 'plan' ) {
474+ if ( ! block . planItems ?. length ) continue
475+ segments . push ( { type : 'plan' , items : block . planItems } )
476+ continue
477+ }
478+
458479 if ( block . type === 'subagent_end' ) {
459480 if ( block . spanId ) {
460481 const g = groupsBySpanId . get ( block . spanId )
@@ -706,6 +727,13 @@ function parseBlocksLegacy(blocks: ContentBlock[]): MessageSegment[] {
706727 continue
707728 }
708729
730+ if ( block . type === 'plan' ) {
731+ if ( ! block . planItems ?. length ) continue
732+ flushLanes ( )
733+ segments . push ( { type : 'plan' , items : block . planItems } )
734+ continue
735+ }
736+
709737 if ( block . type === 'subagent_end' ) {
710738 if ( block . parentToolCallId ) {
711739 for ( const [ key , g ] of groupsByKey ) {
@@ -1016,6 +1044,8 @@ function MessageContentInner({
10161044 < Options items = { segment . items } onSelect = { onOptionSelect } />
10171045 </ div >
10181046 )
1047+ case 'plan' :
1048+ return < PlanChecklist key = { `plan-${ i } ` } items = { segment . items } />
10191049 // The stopped row renders in the tail region below, in the
10201050 // shimmer's place — a stop while the shimmer is visible must read
10211051 // as an in-place replacement, not the shimmer vanishing from the
0 commit comments