import { CodeEditor } from "@/components/ui/codeEditor"; import { ResponsesMessage, ResponsesMessageContentBlock } from "@/lib/types/logs"; import { cleanJson, isJson } from "@/lib/utils/validation"; import CollapsibleBox from "./collapsibleBox"; interface LogResponsesMessageViewProps { messages: ResponsesMessage[]; } function ContentBlockView({ block }: { block: ResponsesMessageContentBlock; index: number }) { const getBlockTitle = (type: string) => { switch (type) { case "input_text": return "Input Text"; case "input_image": return "Input Image"; case "input_file": return "Input File"; case "input_audio": return "Input Audio"; case "output_text": return "Output Text"; case "reasoning_text": return "Reasoning Text"; case "refusal": return "Refusal"; default: return type.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()); } }; const blockTitle = getBlockTitle(block.type); // Handle text content if (block.text) { if (isJson(block.text)) { const jsonContent = JSON.stringify(cleanJson(block.text), null, 2); return ( jsonContent} collapsedHeight={100}> ); } return ( block.text || ""} collapsedHeight={100}>
{block.text}
); } // Handle image content if (block.image_url) { const jsonContent = JSON.stringify( { image_url: block.image_url, ...(block.detail && { detail: block.detail }), }, null, 2, ); return ( jsonContent} collapsedHeight={100}> ); } // Handle file content if (block.file_id || block.file_data || block.file_url) { const jsonContent = JSON.stringify( { ...(block.filename && { filename: block.filename }), ...(block.file_id && { file_id: block.file_id }), ...(block.file_url && { file_url: block.file_url }), ...(block.file_data && { file_data: "[Base64 encoded data]" }), }, null, 2, ); return ( jsonContent} collapsedHeight={100}> ); } // Handle audio content if (block.input_audio) { const jsonContent = JSON.stringify(block.input_audio, null, 2); return ( jsonContent} collapsedHeight={100}> ); } // Handle refusal content if (block.refusal) { return ( block.refusal || ""} collapsedHeight={100}>
{block.refusal}
); } // Handle annotations if (block.annotations && block.annotations.length > 0) { const jsonContent = JSON.stringify(block.annotations, null, 2); return ( jsonContent} collapsedHeight={100}> ); } // Handle log probabilities if (block.logprobs && block.logprobs.length > 0) { const jsonContent = JSON.stringify(block.logprobs, null, 2); return ( jsonContent} collapsedHeight={100}> ); } return null; } function MessageView({ message, index }: { message: ResponsesMessage; index: number }) { const getMessageTitle = () => { if (message.type) { switch (message.type) { case "reasoning": return "Reasoning"; case "message": return message.role ? `${message.role.charAt(0).toUpperCase() + message.role.slice(1)} Message` : "Message"; case "function_call": return `Function Call: ${message.name || "Unknown"}`; case "function_call_output": return `Function Call Output${message.call_id ? `: ${message.call_id}` : ""}`; case "file_search_call": return "File Search"; case "web_search_call": return "Web Search"; case "computer_call": return "Computer Action"; case "computer_call_output": return "Computer Action Output"; case "code_interpreter_call": return "Code Interpreter"; case "mcp_call": return "MCP Tool Call"; case "custom_tool_call": return "Custom Tool Call"; case "custom_tool_call_output": return "Custom Tool Output"; case "image_generation_call": return "Image Generation"; case "refusal": return "Refusal"; default: return message.type.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()); } } return message.role ? `${message.role.charAt(0).toUpperCase() + message.role.slice(1)}` : "Message"; }; if (message.type == "reasoning" && (!message.summary || message.summary.length === 0) && !message.encrypted_content && !message.content) { return null; } const messageTitle = getMessageTitle(); return (
{/* Message title header */}
{messageTitle}
{/* Handle reasoning content */} {message.type === "reasoning" && message.summary && message.summary.length > 0 && ( <> {message.summary.every((item) => item.type === "summary_text") ? ( // Display as readable text when all items are summary_text message.summary.map((reasoningContent, idx) => ( reasoningContent.text || ""} collapsedHeight={100}>
{reasoningContent.text}
)) ) : ( // Fallback to JSON display for mixed or non-text types JSON.stringify(message.summary, null, 2)} collapsedHeight={100}> )} )} {/* Handle encrypted reasoning content */} {message.type === "reasoning" && message.encrypted_content && ( message.encrypted_content || ""} collapsedHeight={100}>
{message.encrypted_content}
)} {/* Handle regular content */} {message.content && ( <> {typeof message.content === "string" ? ( <> {isJson(message.content) ? ( JSON.stringify(cleanJson(message.content as string), null, 2)} collapsedHeight={100} > ) : ( (message.content as string) || ""} collapsedHeight={100}>
{message.content}
)} ) : ( Array.isArray(message.content) && message.content.map((block, blockIndex) => ) )} )} {/* Handle tool call specific fields */} {(message.call_id || message.name || message.arguments) && ( JSON.stringify( { ...(message.call_id && { call_id: message.call_id }), ...(message.name && { name: message.name }), ...(message.arguments && { arguments: isJson(message.arguments) ? cleanJson(message.arguments) : message.arguments }), }, null, 2, ) } collapsedHeight={100} > )} {/* Handle function call output */} {message.output !== undefined && ( (typeof message.output === "string" ? message.output : JSON.stringify(message.output, null, 2))} collapsedHeight={100} > {typeof message.output === "string" ? ( isJson(message.output) ? ( ) : (
{message.output}
) ) : ( )}
)} {/* Handle additional tool-specific fields */} {Object.keys(message).some( (key) => !["id", "type", "status", "role", "content", "call_id", "name", "arguments", "summary", "encrypted_content", "output"].includes(key), ) && ( JSON.stringify( Object.fromEntries( Object.entries(message).filter( ([key]) => !["id", "type", "status", "role", "content", "call_id", "name", "arguments", "summary", "encrypted_content", "output"].includes( key, ), ), ), null, 2, ) } collapsedHeight={100} > !["id", "type", "status", "role", "content", "call_id", "name", "arguments", "summary", "encrypted_content", "output"].includes( key, ), ), ), null, 2, )} lang="json" readonly={true} options={{ scrollBeyondLastLine: false, collapsibleBlocks: true, lineNumbers: "off", alwaysConsumeMouseWheel: false }} /> )}
); } export default function LogResponsesMessageView({ messages }: LogResponsesMessageViewProps) { if (!messages || messages.length === 0) { return (
No responses messages available
); } return (
{messages.map((message, index) => ( ))}
); }