import { formatCost, formatLatency, formatTokens, } from "@/app/workspace/dashboard/utils/chartUtils"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { ProviderIconType, RenderProviderIcon } from "@/lib/constants/icons"; import { getProviderLabel, ProviderName, RequestTypeColors, RequestTypeLabels, Status, StatusBarColors, } from "@/lib/constants/logs"; import { ChatMessageContent, LogEntry, ResponsesMessageContentBlock, } from "@/lib/types/logs"; import { cn } from "@/lib/utils"; import { ColumnDef } from "@tanstack/react-table"; import { format, formatDistanceToNow } from "date-fns"; import { ArrowUpDown, Trash2 } from "lucide-react"; function getAssistantToolCallSummary(log?: LogEntry): string { const toolCalls = log?.output_message?.tool_calls || []; return toolCalls .map((toolCall) => { const name = toolCall?.function?.name; if (!name) { return ""; } const argumentsText = toolCall?.function?.arguments?.trim(); return argumentsText ? `${name}(${argumentsText})` : name; }) .filter(Boolean) .join("\n"); } function getMessageFromContent(content?: ChatMessageContent): string { if (content == undefined) { return ""; } if (typeof content === "string") { return content; } let lastTextContentBlock = ""; for (const block of content) { if ( (block.type === "text" || block.type === "input_text" || block.type === "output_text") && block.text ) { lastTextContentBlock = block.text; } } return lastTextContentBlock; } export function getRealtimeTurnMessages(log?: LogEntry): { tool?: string; user?: string; assistant?: string; assistantToolCall?: string; } { const toolMessages = log?.input_history?.filter((message) => message.role === "tool") || []; const userMessages = log?.input_history?.filter((message) => message.role === "user") || []; return { tool: toolMessages .map((m) => getMessageFromContent(m.content)) .filter(Boolean) .join("\n") || "", user: userMessages .map((m) => getMessageFromContent(m.content)) .filter(Boolean) .join("\n") || "", assistant: log?.output_message ? getMessageFromContent(log.output_message.content) : "", assistantToolCall: getAssistantToolCallSummary(log), }; } export function getMessage(log?: LogEntry) { if (log?.object === "list_models") { return "N/A"; } if (log?.object === "realtime.turn") { const messages = getRealtimeTurnMessages(log); const parts = [ messages.tool ? `Tool Result: ${messages.tool}` : "", messages.user ? `User: ${messages.user}` : "", messages.assistantToolCall ? `Assistant Tool Call: ${messages.assistantToolCall}` : "", messages.assistant ? `Assistant: ${messages.assistant}` : "", ].filter(Boolean); if (parts.length > 0) { return parts.join("\n"); } return ""; } if (log?.input_history && log.input_history.length > 0) { return getMessageFromContent( log.input_history[log.input_history.length - 1].content, ); } else if ( log?.responses_input_history && log.responses_input_history.length > 0 ) { let lastMessage = log.responses_input_history[log.responses_input_history.length - 1]; let lastMessageContent = lastMessage.content; if (typeof lastMessageContent === "string") { return lastMessageContent; } let lastTextContentBlock = ""; for (const block of (lastMessageContent ?? []) as ResponsesMessageContentBlock[]) { if (block.text && block.text !== "") { lastTextContentBlock = block.text; } } // If no content found in content field, check output field for Responses API if (!lastTextContentBlock && lastMessage.output) { // Handle output field - it could be a string, an array of content blocks, or a computer tool call output data if (typeof lastMessage.output === "string") { return lastMessage.output; } else if (Array.isArray(lastMessage.output)) { return lastMessage.output.map((block) => block.text).join("\n"); } else if ( lastMessage.output.type && lastMessage.output.type === "computer_screenshot" ) { return lastMessage.output.image_url; } } return lastTextContentBlock ?? ""; } else if (log?.output_message) { return getMessageFromContent(log.output_message.content); } else if (log?.speech_input) { return log.speech_input.input; } else if (log?.transcription_input) { return "Audio file"; } else if (log?.image_generation_input?.prompt) { return log.image_generation_input.prompt; } const obj = log?.object as string | undefined; if ( obj === "image_edit" || obj === "image_edit_stream" || obj === "image_variation" ) { return "Image file"; } if (log?.content_summary) { return log.content_summary; } return ""; } export function LogMessageCell({ log, maxWidth = "max-w-[400px]", }: { log: LogEntry; maxWidth?: string; }) { const input = getMessage(log); const isLargePayload = log.is_large_payload_request || log.is_large_payload_response; const realtimeMessages = log.object === "realtime.turn" ? getRealtimeTurnMessages(log) : null; return (