forked from phoenix-oss/llama-stack-mirror
feat(ui): implement chat completion views (#2201)
# What does this PR do? Implements table and detail views for chat completions <img width="1548" alt="image" src="https://github.com/user-attachments/assets/01061b7f-0d47-4b3b-b5ac-2df8f9035ef6" /> <img width="1549" alt="image" src="https://github.com/user-attachments/assets/738d8612-8258-4c2c-858b-bee39030649f" /> ## Test Plan npm run test
This commit is contained in:
parent
d8c6ab9bfc
commit
2708312168
27 changed files with 6729 additions and 38 deletions
|
@ -0,0 +1,107 @@
|
|||
"use client";
|
||||
|
||||
import { ChatMessage } from "@/lib/types";
|
||||
import React from "react";
|
||||
import { formatToolCallToString } from "@/lib/format-tool-call";
|
||||
import { extractTextFromContentPart } from "@/lib/format-message-content";
|
||||
|
||||
// Sub-component or helper for the common label + content structure
|
||||
const MessageBlock: React.FC<{
|
||||
label: string;
|
||||
labelDetail?: string;
|
||||
content: React.ReactNode;
|
||||
}> = ({ label, labelDetail, content }) => {
|
||||
return (
|
||||
<div>
|
||||
<p className="py-1 font-semibold text-gray-800 mb-1">
|
||||
{label}
|
||||
{labelDetail && (
|
||||
<span className="text-xs text-gray-500 font-normal ml-1">
|
||||
{labelDetail}
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
<div className="py-1">{content}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface ToolCallBlockProps {
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ToolCallBlock = ({ children, className }: ToolCallBlockProps) => {
|
||||
// Common styling for both function call arguments and tool output blocks
|
||||
// Let's use slate-50 background as it's good for code-like content.
|
||||
const baseClassName =
|
||||
"p-3 bg-slate-50 border border-slate-200 rounded-md text-sm";
|
||||
|
||||
return (
|
||||
<div className={`${baseClassName} ${className || ""}`}>
|
||||
<pre className="whitespace-pre-wrap text-xs">{children}</pre>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface ChatMessageItemProps {
|
||||
message: ChatMessage;
|
||||
}
|
||||
export function ChatMessageItem({ message }: ChatMessageItemProps) {
|
||||
switch (message.role) {
|
||||
case "system":
|
||||
return (
|
||||
<MessageBlock
|
||||
label="System"
|
||||
content={extractTextFromContentPart(message.content)}
|
||||
/>
|
||||
);
|
||||
case "user":
|
||||
return (
|
||||
<MessageBlock
|
||||
label="User"
|
||||
content={extractTextFromContentPart(message.content)}
|
||||
/>
|
||||
);
|
||||
|
||||
case "assistant":
|
||||
if (message.tool_calls && message.tool_calls.length > 0) {
|
||||
return (
|
||||
<>
|
||||
{message.tool_calls.map((toolCall: any, index: number) => {
|
||||
const formattedToolCall = formatToolCallToString(toolCall);
|
||||
const toolCallContent = (
|
||||
<ToolCallBlock>
|
||||
{formattedToolCall || "Error: Could not display tool call"}
|
||||
</ToolCallBlock>
|
||||
);
|
||||
return (
|
||||
<MessageBlock
|
||||
key={index}
|
||||
label="Tool Call"
|
||||
content={toolCallContent}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<MessageBlock
|
||||
label="Assistant"
|
||||
content={extractTextFromContentPart(message.content)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
case "tool":
|
||||
const toolOutputContent = (
|
||||
<ToolCallBlock>
|
||||
{extractTextFromContentPart(message.content)}
|
||||
</ToolCallBlock>
|
||||
);
|
||||
return (
|
||||
<MessageBlock label="Tool Call Output" content={toolOutputContent} />
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue