import { NormalizedConversationViewer } from '@/components/tasks/TaskDetails/NormalizedConversationViewer.tsx'; import { useCallback, useContext, useEffect, useMemo, useRef, useState, } from 'react'; import { TaskAttemptDataContext } from '@/components/context/taskDetailsContext.ts'; type Props = { conversationUpdateTrigger: number; handleConversationUpdate: () => void; }; function Conversation({ conversationUpdateTrigger, handleConversationUpdate, }: Props) { const { attemptData } = useContext(TaskAttemptDataContext); const [shouldAutoScrollLogs, setShouldAutoScrollLogs] = useState(true); const scrollContainerRef = useRef(null); useEffect(() => { if (shouldAutoScrollLogs && scrollContainerRef.current) { scrollContainerRef.current.scrollTop = scrollContainerRef.current.scrollHeight; } }, [ attemptData.activities, attemptData.processes, conversationUpdateTrigger, shouldAutoScrollLogs, ]); const handleLogsScroll = useCallback(() => { if (scrollContainerRef.current) { const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current; const isAtBottom = scrollTop + clientHeight >= scrollHeight - 5; if (isAtBottom && !shouldAutoScrollLogs) { setShouldAutoScrollLogs(true); } else if (!isAtBottom && shouldAutoScrollLogs) { setShouldAutoScrollLogs(false); } } }, [shouldAutoScrollLogs]); const mainCodingAgentProcess = useMemo(() => { let mainCAProcess = Object.values(attemptData.runningProcessDetails).find( (process) => process.process_type === 'codingagent' && process.command === 'executor' ); if (!mainCAProcess) { const mainCodingAgentSummary = attemptData.processes.find( (process) => process.process_type === 'codingagent' && process.command === 'executor' ); if (mainCodingAgentSummary) { mainCAProcess = Object.values(attemptData.runningProcessDetails).find( (process) => process.id === mainCodingAgentSummary.id ); if (!mainCAProcess) { mainCAProcess = { ...mainCodingAgentSummary, stdout: null, stderr: null, } as any; } } } return mainCAProcess; }, [attemptData.processes, attemptData.runningProcessDetails]); const followUpProcesses = useMemo(() => { return attemptData.processes .filter( (process) => process.process_type === 'codingagent' && process.command === 'followup_executor' ) .map((summary) => { const detailedProcess = Object.values( attemptData.runningProcessDetails ).find((process) => process.id === summary.id); return ( detailedProcess || ({ ...summary, stdout: null, stderr: null, } as any) ); }); }, [attemptData.processes, attemptData.runningProcessDetails]); return (
{mainCodingAgentProcess || followUpProcesses.length > 0 ? (
{mainCodingAgentProcess && (
)} {followUpProcesses.map((followUpProcess) => (
))}
) : (

Coding Agent Starting

Initializing conversation...

)}
); } export default Conversation;