diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/RealtimePrettyView.test.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/RealtimePrettyView.test.tsx
index ea908552395..4a0adecc967 100644
--- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/RealtimePrettyView.test.tsx
+++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/RealtimePrettyView.test.tsx
@@ -187,6 +187,49 @@ describe("RealtimePrettyView", () => {
expect(screen.getByText("text")).toBeInTheDocument();
});
+ it("should display the turn count in session header", () => {
+ render();
+ expect(screen.getByText("2 turns")).toBeInTheDocument();
+ });
+
+ it("should display singular 'turn' for a single response event", () => {
+ const singleTurnResponse = {
+ results: [
+ {
+ type: "session.created",
+ session: {
+ id: "sess_1",
+ model: "gpt-4o-mini-realtime-preview",
+ voice: "alloy",
+ modalities: ["audio"],
+ },
+ },
+ {
+ type: "response.done",
+ response: {
+ id: "r1",
+ status: "completed",
+ output: [
+ {
+ id: "item1",
+ role: "assistant",
+ type: "message",
+ content: [{ type: "audio", transcript: "Hi!" }],
+ },
+ ],
+ },
+ },
+ ],
+ };
+ render();
+ expect(screen.getByText("1 turn")).toBeInTheDocument();
+ });
+
+ it("should display the turn count in the output section header", () => {
+ render();
+ expect(screen.getByText("Turns: 2")).toBeInTheDocument();
+ });
+
it("should display the Output section header", () => {
render();
expect(screen.getByText("Output")).toBeInTheDocument();
diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/RealtimePrettyView.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/RealtimePrettyView.tsx
index af048fe5042..94593c21fed 100644
--- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/RealtimePrettyView.tsx
+++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/RealtimePrettyView.tsx
@@ -107,7 +107,7 @@ export function RealtimePrettyView({ response, metrics }: RealtimePrettyViewProp
{/* Session Configuration Card */}
{sessionEvent?.session && (
-
+
)}
{/* Conversation Turns */}
@@ -138,7 +138,7 @@ export function RealtimePrettyView({ response, metrics }: RealtimePrettyViewProp
);
}
-function SessionCard({ session }: { session: RealtimeSession }) {
+function SessionCard({ session, turnCount }: { session: RealtimeSession; turnCount: number }) {
const [isCollapsed, setIsCollapsed] = useState(true);
return (
@@ -184,6 +184,14 @@ function SessionCard({ session }: { session: RealtimeSession }) {
{session.model}
+ {turnCount > 0 && (
+
+ {turnCount} {turnCount === 1 ? 'turn' : 'turns'}
+
+ )}
{session.voice && (
{session.voice}
@@ -298,6 +306,7 @@ function ConversationCard({
const [isCollapsed, setIsCollapsed] = useState(false);
const totalTokens = totalUsage?.total_tokens;
+ const turnCount = responses.length;
const handleCopy = () => {
const transcripts = responses
.flatMap((r) =>
@@ -326,6 +335,7 @@ function ConversationCard({
onCopy={handleCopy}
isCollapsed={isCollapsed}
onToggleCollapse={() => setIsCollapsed(!isCollapsed)}
+ turnCount={turnCount}
/>
void;
isCollapsed?: boolean;
onToggleCollapse?: () => void;
+ turnCount?: number;
}
-export function SectionHeader({ type, tokens, cost, onCopy, isCollapsed, onToggleCollapse }: SectionHeaderProps) {
+export function SectionHeader({ type, tokens, cost, onCopy, isCollapsed, onToggleCollapse, turnCount }: SectionHeaderProps) {
return (
)}
+
+ {/* Turn count */}
+ {turnCount !== undefined && turnCount > 0 && (
+
+ Turns: {turnCount}
+
+ )}
{/* Copy Button */}