11"use client" ;
22
33import React , { useMemo , useState , useCallback } from "react" ;
4- import { RotateCcw } from "lucide-react" ;
54import { SubAgentIndicator } from "@/app/components/SubAgentIndicator" ;
65import { ToolCallBox } from "@/app/components/ToolCallBox" ;
76import { MarkdownContent } from "@/app/components/MarkdownContent" ;
8- import type { SubAgent , ToolCall } from "@/app/types/types" ;
9- import { Interrupt , Message } from "@langchain/langgraph-sdk" ;
7+ import type {
8+ SubAgent ,
9+ ToolCall ,
10+ ActionRequest ,
11+ ReviewConfig ,
12+ } from "@/app/types/types" ;
13+ import { Message } from "@langchain/langgraph-sdk" ;
1014import {
1115 extractSubAgentContent ,
1216 extractStringFromMessageContent ,
13- getInterruptTitle ,
1417} from "@/app/utils/utils" ;
1518import { cn } from "@/lib/utils" ;
1619
1720interface ChatMessageProps {
1821 message : Message ;
1922 toolCalls : ToolCall [ ] ;
20- onRestartFromAIMessage : ( message : Message ) => void ;
21- onRestartFromSubTask : ( toolCallId : string ) => void ;
22- debugMode ?: boolean ;
23- isLastMessage ?: boolean ;
2423 isLoading ?: boolean ;
25- interrupt ?: Interrupt ;
24+ actionRequestsMap ?: Map < string , ActionRequest > ;
25+ reviewConfigsMap ?: Map < string , ReviewConfig > ;
2626 ui ?: any [ ] ;
2727 stream ?: any ;
28+ onResumeInterrupt ?: ( value : any ) => void ;
29+ graphId ?: string ;
2830}
2931
3032export const ChatMessage = React . memo < ChatMessageProps > (
3133 ( {
3234 message,
3335 toolCalls,
34- onRestartFromAIMessage,
35- onRestartFromSubTask,
36- debugMode,
37- isLastMessage,
3836 isLoading,
39- interrupt,
37+ actionRequestsMap,
38+ reviewConfigsMap,
4039 ui,
4140 stream,
41+ onResumeInterrupt,
42+ graphId,
4243 } ) => {
4344 const isUser = message . type === "human" ;
44- const isAIMessage = message . type === "ai" ;
4545 const messageContent = extractStringFromMessageContent ( message ) ;
4646 const hasContent = messageContent && messageContent . trim ( ) !== "" ;
4747 const hasToolCalls = toolCalls . length > 0 ;
@@ -56,10 +56,13 @@ export const ChatMessage = React.memo<ChatMessageProps>(
5656 ) ;
5757 } )
5858 . map ( ( toolCall : ToolCall ) => {
59+ const subagentType = ( toolCall . args as Record < string , unknown > ) [
60+ "subagent_type"
61+ ] as string ;
5962 return {
6063 id : toolCall . id ,
6164 name : toolCall . name ,
62- subAgentName : String ( toolCall . args [ "subagent_type" ] || "" ) ,
65+ subAgentName : subagentType ,
6366 input : toolCall . args ,
6467 output : toolCall . result ? { result : toolCall . result } : undefined ,
6568 status : toolCall . status ,
@@ -81,8 +84,6 @@ export const ChatMessage = React.memo<ChatMessageProps>(
8184 } ) ) ;
8285 } , [ ] ) ;
8386
84- const interruptTitle = interrupt ? getInterruptTitle ( interrupt ) : "" ;
85-
8687 return (
8788 < div
8889 className = { cn (
@@ -96,7 +97,7 @@ export const ChatMessage = React.memo<ChatMessageProps>(
9697 isUser ? "max-w-[70%]" : "w-full"
9798 ) }
9899 >
99- { ( hasContent || debugMode ) && (
100+ { hasContent && (
100101 < div className = { cn ( "relative flex items-end gap-0" ) } >
101102 < div
102103 className = { cn (
@@ -117,40 +118,30 @@ export const ChatMessage = React.memo<ChatMessageProps>(
117118 </ p >
118119 ) : hasContent ? (
119120 < MarkdownContent content = { messageContent } />
120- ) : debugMode ? (
121- < p className = "m-0 whitespace-nowrap text-xs italic" >
122- Empty Message
123- </ p >
124121 ) : null }
125122 </ div >
126- { debugMode && isAIMessage && ! ( isLastMessage && isLoading ) && (
127- < button
128- onClick = { ( ) => onRestartFromAIMessage ( message ) }
129- className = "absolute bottom-1 right-1 -scale-x-100 rounded-full bg-black/10 p-1 transition-colors duration-200 hover:bg-black/20"
130- >
131- < RotateCcw className = "h-3 w-3 text-gray-600" />
132- </ button >
133- ) }
134123 </ div >
135124 ) }
136125 { hasToolCalls && (
137126 < div className = "mt-4 flex w-full flex-col" >
138- { toolCalls . map ( ( toolCall : ToolCall , idx , arr ) => {
127+ { toolCalls . map ( ( toolCall : ToolCall ) => {
139128 if ( toolCall . name === "task" ) return null ;
140- const uiComponent = ui ?. find (
129+ const toolCallGenUiComponent = ui ?. find (
141130 ( u ) => u . metadata ?. tool_call_id === toolCall . id
142131 ) ;
143- const isInterrupted =
144- idx === arr . length - 1 &&
145- toolCall . name === interruptTitle &&
146- isLastMessage ;
132+ const actionRequest = actionRequestsMap ?. get ( toolCall . name ) ;
133+ const reviewConfig = reviewConfigsMap ?. get ( toolCall . name ) ;
147134 return (
148135 < ToolCallBox
149136 key = { toolCall . id }
150137 toolCall = { toolCall }
151- uiComponent = { uiComponent }
138+ uiComponent = { toolCallGenUiComponent }
152139 stream = { stream }
153- isInterrupted = { isInterrupted }
140+ graphId = { graphId }
141+ actionRequest = { actionRequest }
142+ reviewConfig = { reviewConfig }
143+ onResume = { onResumeInterrupt }
144+ isLoading = { isLoading }
154145 />
155146 ) ;
156147 } ) }
@@ -171,16 +162,6 @@ export const ChatMessage = React.memo<ChatMessageProps>(
171162 isExpanded = { isSubAgentExpanded ( subAgent . id ) }
172163 />
173164 </ div >
174- < div className = "relative h-full min-h-[40px] w-[72px] flex-shrink-0" >
175- { debugMode && subAgent . status === "completed" && (
176- < button
177- onClick = { ( ) => onRestartFromSubTask ( subAgent . id ) }
178- className = "absolute bottom-1 right-1 -scale-x-100 rounded-full bg-black/10 p-1 transition-colors duration-200 hover:bg-black/20"
179- >
180- < RotateCcw className = "h-3 w-3 text-gray-600" />
181- </ button >
182- ) }
183- </ div >
184165 </ div >
185166 { isSubAgentExpanded ( subAgent . id ) && (
186167 < div className = "w-full max-w-full" >
0 commit comments