setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
+ >
+ {/* Role Label Row */}
+
+
+ {style.label}
+
+
+
+ {/* Tool Calls with left border */}
+
+ {message.toolCalls!.map((tool, index) => (
+
+ ))}
+
+
+ );
+ }
+
+ const handleCopy = () => {
+ navigator.clipboard.writeText(content);
+ antdMessage.success('Message copied');
+ };
+
+ return (
+ setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
+ >
+ {/* Role Label Row */}
+
+
+ {style.label}
+ {isLong && (
+
+ ({content.length.toLocaleString()} chars)
+
+ )}
+
+
+ {/* Copy Button - Show on hover */}
+ {hasContent && (
+ }
+ style={{
+ opacity: isHovered ? 1 : 0,
+ transition: 'opacity 0.2s',
+ }}
+ onClick={handleCopy}
+ />
+ )}
+
+
+ {/* Content with left border accent */}
+ {hasContent && (
+
+ {shouldTruncate ? (
+ <>
+ {content.slice(0, TRUNCATE_LENGTH)}...
+
+ >
+ ) : (
+ <>
+ {content}
+ {isLong && !isCollapsed && (
+
+ )}
+ >
+ )}
+
+ )}
+
+ {/* Tool Calls (for assistant messages) */}
+ {hasToolCalls && hasContent && (
+
+ {message.toolCalls!.map((tool, index) => (
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/PrettyMessagesView.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/PrettyMessagesView.tsx
new file mode 100644
index 00000000000..4b125cbd7b7
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/PrettyMessagesView.tsx
@@ -0,0 +1,108 @@
+/**
+ * PrettyMessagesView - Chat-style view of request and response messages
+ * Replaces raw JSON with scannable, readable message cards
+ */
+
+import { Typography } from 'antd';
+import { parseMessages } from './prettyMessagesUtils';
+import { MessageCard } from './MessageCard';
+import { HistorySection } from './HistorySection';
+
+const { Text } = Typography;
+
+interface PrettyMessagesViewProps {
+ request: any;
+ response: any;
+}
+
+export function PrettyMessagesView({ request, response }: PrettyMessagesViewProps) {
+ const { requestMessages, responseMessage } = parseMessages(request, response);
+
+ // Separate system, history, and last user message
+ const systemMessage = requestMessages.find((m) => m.role === 'system');
+ const nonSystemMessages = requestMessages.filter((m) => m.role !== 'system');
+ const lastUserMessage =
+ nonSystemMessages.length > 0 ? nonSystemMessages[nonSystemMessages.length - 1] : null;
+ const historyMessages = nonSystemMessages.slice(0, -1);
+
+ return (
+
+ {/* REQUEST SECTION */}
+
+
+ Request ({requestMessages.length} message{requestMessages.length !== 1 ? 's' : ''})
+
+
+ {/* System Message - Collapsed by default */}
+ {systemMessage &&
}
+
+ {/* History - Collapsed if > 0 messages */}
+ {historyMessages.length > 0 &&
}
+
+ {/* Last User Message - Always expanded */}
+ {lastUserMessage && lastUserMessage.role === 'user' && (
+
+ )}
+
+ {/* Fallback if no messages */}
+ {requestMessages.length === 0 && (
+
+ No request messages available
+
+ )}
+
+
+ {/* Section Divider */}
+
+
+ Response
+
+
+ {/* RESPONSE SECTION */}
+ {responseMessage ? (
+
+ ) : (
+
+ Response data not available
+
+ )}
+
+
+ );
+}
diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/ToolCallCard.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/ToolCallCard.tsx
new file mode 100644
index 00000000000..38f2128a3db
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/ToolCallCard.tsx
@@ -0,0 +1,79 @@
+/**
+ * ToolCallCard - Display tool call information inline in assistant messages
+ */
+
+import { useState } from 'react';
+import { Button, Typography, message } from 'antd';
+import { CopyOutlined, ToolOutlined } from '@ant-design/icons';
+import { ToolCall } from './prettyMessagesTypes';
+
+const { Text } = Typography;
+
+interface ToolCallCardProps {
+ tool: ToolCall;
+}
+
+export function ToolCallCard({ tool }: ToolCallCardProps) {
+ const [isHovered, setIsHovered] = useState(false);
+
+ const handleCopy = () => {
+ navigator.clipboard.writeText(JSON.stringify(tool.arguments, null, 2));
+ message.success('Tool arguments copied');
+ };
+
+ return (
+ setIsHovered(true)}
+ onMouseLeave={() => setIsHovered(false)}
+ >
+ {/* Tool Header */}
+
0 ? 6 : 0,
+ }}
+ >
+
+ {tool.name}
+
+ }
+ style={{
+ opacity: isHovered ? 1 : 0,
+ transition: 'opacity 0.2s',
+ }}
+ onClick={handleCopy}
+ />
+
+
+ {/* Tool Arguments - Simple key: value format */}
+ {Object.keys(tool.arguments).length > 0 && (
+
+ {Object.entries(tool.arguments).map(([key, value]) => (
+
+
+ {key}:
+ {' '}
+
+ {JSON.stringify(value)}
+
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/prettyMessagesTypes.ts b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/prettyMessagesTypes.ts
new file mode 100644
index 00000000000..1f4e23f5bd3
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/prettyMessagesTypes.ts
@@ -0,0 +1,28 @@
+/**
+ * Type definitions for pretty messages view
+ */
+
+export interface ParsedMessage {
+ role: 'system' | 'user' | 'assistant' | 'tool';
+ content: string;
+ toolCalls?: ToolCall[];
+ toolCallId?: string;
+}
+
+export interface ToolCall {
+ id: string;
+ name: string;
+ arguments: Record