@@ -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'
@@ -74,7 +76,17 @@ interface StoppedSegment {
7476 type : 'stopped'
7577}
7678
77- type MessageSegment = TextSegment | AgentGroupSegment | OptionsSegment | StoppedSegment
79+ interface PlanSegment {
80+ type : 'plan'
81+ items : AgentPlanItem [ ]
82+ }
83+
84+ type MessageSegment =
85+ | TextSegment
86+ | AgentGroupSegment
87+ | OptionsSegment
88+ | StoppedSegment
89+ | PlanSegment
7890
7991function getAgentGroupActivityKey ( items : AgentGroupItem [ ] ) : string {
8092 return items
@@ -115,6 +127,9 @@ function getVisibleStreamActivityKey(segments: MessageSegment[]): string {
115127 return `options:${ segment . items . map ( ( item ) => `${ item . id } :${ item . label . length } ` ) . join ( ',' ) } `
116128 }
117129 if ( segment . type === 'stopped' ) return 'stopped'
130+ if ( segment . type === 'plan' ) {
131+ return `plan:${ segment . items . map ( ( item ) => `${ item . status } :${ item . step . length } ` ) . join ( ',' ) } `
132+ }
118133 return [
119134 'agent' ,
120135 segment . id ,
@@ -462,6 +477,12 @@ function parseBlocksWithSpanTree(blocks: ContentBlock[]): MessageSegment[] {
462477 continue
463478 }
464479
480+ if ( block . type === 'plan' ) {
481+ if ( ! block . planItems ?. length ) continue
482+ segments . push ( { type : 'plan' , items : block . planItems } )
483+ continue
484+ }
485+
465486 if ( block . type === 'subagent_end' ) {
466487 if ( block . spanId ) {
467488 const g = groupsBySpanId . get ( block . spanId )
@@ -713,6 +734,13 @@ function parseBlocksLegacy(blocks: ContentBlock[]): MessageSegment[] {
713734 continue
714735 }
715736
737+ if ( block . type === 'plan' ) {
738+ if ( ! block . planItems ?. length ) continue
739+ flushLanes ( )
740+ segments . push ( { type : 'plan' , items : block . planItems } )
741+ continue
742+ }
743+
716744 if ( block . type === 'subagent_end' ) {
717745 if ( block . parentToolCallId ) {
718746 for ( const [ key , g ] of groupsByKey ) {
@@ -1046,6 +1074,8 @@ function MessageContentInner({
10461074 < Options items = { segment . items } onSelect = { onOptionSelect } />
10471075 </ div >
10481076 )
1077+ case 'plan' :
1078+ return < PlanChecklist key = { `plan-${ i } ` } items = { segment . items } />
10491079 // The stopped row renders in the tail region below, in the
10501080 // shimmer's place — a stop while the shimmer is visible must read
10511081 // as an in-place replacement, not the shimmer vanishing from the
0 commit comments