mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-06-27 18:50:41 +00:00
# What does this PR do? * Add responses list and detail views * Refactored components to be shared as much as possible between chat completions and responses ## Test Plan <img width="2014" alt="image" src="https://github.com/user-attachments/assets/6dee12ea-8876-4351-a6eb-2338058466ef" /> <img width="2021" alt="image" src="https://github.com/user-attachments/assets/6c7c71b8-25b7-4199-9c57-6960be5580c8" /> added tests
145 lines
4.1 KiB
TypeScript
145 lines
4.1 KiB
TypeScript
"use client";
|
|
|
|
import { ChatMessage, ChatCompletion } from "@/lib/types";
|
|
import { ChatMessageItem } from "@/components/chat-completions/chat-messasge-item";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import {
|
|
DetailLoadingView,
|
|
DetailErrorView,
|
|
DetailNotFoundView,
|
|
DetailLayout,
|
|
PropertiesCard,
|
|
PropertyItem,
|
|
} from "@/components/layout/detail-layout";
|
|
|
|
interface ChatCompletionDetailViewProps {
|
|
completion: ChatCompletion | null;
|
|
isLoading: boolean;
|
|
error: Error | null;
|
|
id: string;
|
|
}
|
|
|
|
export function ChatCompletionDetailView({
|
|
completion,
|
|
isLoading,
|
|
error,
|
|
id,
|
|
}: ChatCompletionDetailViewProps) {
|
|
const title = "Chat Completion Details";
|
|
|
|
if (error) {
|
|
return <DetailErrorView title={title} id={id} error={error} />;
|
|
}
|
|
|
|
if (isLoading) {
|
|
return <DetailLoadingView title={title} />;
|
|
}
|
|
|
|
if (!completion) {
|
|
return <DetailNotFoundView title={title} id={id} />;
|
|
}
|
|
|
|
// Main content cards
|
|
const mainContent = (
|
|
<>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Input</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{completion.input_messages?.map((msg, index) => (
|
|
<ChatMessageItem key={`input-msg-${index}`} message={msg} />
|
|
))}
|
|
{completion.choices?.[0]?.message?.tool_calls &&
|
|
Array.isArray(completion.choices[0].message.tool_calls) &&
|
|
!completion.input_messages?.some(
|
|
(im) =>
|
|
im.role === "assistant" &&
|
|
im.tool_calls &&
|
|
Array.isArray(im.tool_calls) &&
|
|
im.tool_calls.length > 0,
|
|
)
|
|
? completion.choices[0].message.tool_calls.map(
|
|
(toolCall: any, index: number) => {
|
|
const assistantToolCallMessage: ChatMessage = {
|
|
role: "assistant",
|
|
tool_calls: [toolCall],
|
|
content: "", // Ensure content is defined, even if empty
|
|
};
|
|
return (
|
|
<ChatMessageItem
|
|
key={`choice-tool-call-${index}`}
|
|
message={assistantToolCallMessage}
|
|
/>
|
|
);
|
|
},
|
|
)
|
|
: null}
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Output</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{completion.choices?.[0]?.message ? (
|
|
<ChatMessageItem
|
|
message={completion.choices[0].message as ChatMessage}
|
|
/>
|
|
) : (
|
|
<p className="text-gray-500 italic text-sm">
|
|
No message found in assistant's choice.
|
|
</p>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</>
|
|
);
|
|
|
|
// Properties sidebar
|
|
const sidebar = (
|
|
<PropertiesCard>
|
|
<PropertyItem
|
|
label="Created"
|
|
value={new Date(completion.created * 1000).toLocaleString()}
|
|
/>
|
|
<PropertyItem label="ID" value={completion.id} />
|
|
<PropertyItem label="Model" value={completion.model} />
|
|
<PropertyItem
|
|
label="Finish Reason"
|
|
value={completion.choices?.[0]?.finish_reason || "N/A"}
|
|
hasBorder
|
|
/>
|
|
{(() => {
|
|
const toolCalls = completion.choices?.[0]?.message?.tool_calls;
|
|
if (toolCalls && Array.isArray(toolCalls) && toolCalls.length > 0) {
|
|
return (
|
|
<PropertyItem
|
|
label="Functions/Tools Called"
|
|
value={
|
|
<div>
|
|
<ul className="list-disc list-inside pl-4 mt-1">
|
|
{toolCalls.map((toolCall: any, index: number) => (
|
|
<li key={index}>
|
|
<span className="text-gray-900 font-medium">
|
|
{toolCall.function?.name || "N/A"}
|
|
</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
}
|
|
hasBorder
|
|
/>
|
|
);
|
|
}
|
|
return null;
|
|
})()}
|
|
</PropertiesCard>
|
|
);
|
|
|
|
return (
|
|
<DetailLayout title={title} mainContent={mainContent} sidebar={sidebar} />
|
|
);
|
|
}
|