mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
feat: show turn count in realtime pretty view session header and output header
- Add purple 'N turns' tag to Session card header for at-a-glance turn count - Add 'Turns: N' to the Output section header next to tokens/cost - Extend SectionHeader to accept optional turnCount prop - Add 3 new tests for turn count display (singular, plural, output header) Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
This commit is contained in:
parent
408e5e48bf
commit
1f0cb4705c
3 changed files with 64 additions and 3 deletions
|
|
@ -187,6 +187,49 @@ describe("RealtimePrettyView", () => {
|
|||
expect(screen.getByText("text")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should display the turn count in session header", () => {
|
||||
render(<RealtimePrettyView response={sampleRealtimeResponse} />);
|
||||
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(<RealtimePrettyView response={singleTurnResponse} />);
|
||||
expect(screen.getByText("1 turn")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should display the turn count in the output section header", () => {
|
||||
render(<RealtimePrettyView response={sampleRealtimeResponse} />);
|
||||
expect(screen.getByText("Turns: 2")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should display the Output section header", () => {
|
||||
render(<RealtimePrettyView response={sampleRealtimeResponse} />);
|
||||
expect(screen.getByText("Output")).toBeInTheDocument();
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ export function RealtimePrettyView({ response, metrics }: RealtimePrettyViewProp
|
|||
<div>
|
||||
{/* Session Configuration Card */}
|
||||
{sessionEvent?.session && (
|
||||
<SessionCard session={sessionEvent.session} />
|
||||
<SessionCard session={sessionEvent.session} turnCount={responseEvents.length} />
|
||||
)}
|
||||
|
||||
{/* 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 }) {
|
|||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{session.model}
|
||||
</Text>
|
||||
{turnCount > 0 && (
|
||||
<Tag
|
||||
color="purple"
|
||||
style={{ margin: 0, fontWeight: 500 }}
|
||||
>
|
||||
{turnCount} {turnCount === 1 ? 'turn' : 'turns'}
|
||||
</Tag>
|
||||
)}
|
||||
{session.voice && (
|
||||
<Tag color="blue" style={{ margin: 0 }}>
|
||||
<SoundOutlined /> {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}
|
||||
/>
|
||||
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ interface SectionHeaderProps {
|
|||
onCopy: () => 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 (
|
||||
<div
|
||||
onClick={onToggleCollapse}
|
||||
|
|
@ -81,6 +82,13 @@ export function SectionHeader({ type, tokens, cost, onCopy, isCollapsed, onToggl
|
|||
Cost: ${cost.toFixed(6)}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{/* Turn count */}
|
||||
{turnCount !== undefined && turnCount > 0 && (
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
Turns: {turnCount}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Copy Button */}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue