feat: add PromptExecutions detail page with execution monitoring and metrics tracking

This commit is contained in:
sibarchannayak 2026-05-29 15:15:04 +05:30
parent b6e594611e
commit 9415e9e9bf

View File

@ -8,8 +8,6 @@ import {
Pagination, Pagination,
FilterDropdown, FilterDropdown,
GradientStatCard, GradientStatCard,
PrimaryButton,
SecondaryButton,
MarkdownViewer, MarkdownViewer,
} from "@/components/shared"; } from "@/components/shared";
import { aiService } from "@/services/ai-service"; import { aiService } from "@/services/ai-service";
@ -17,13 +15,10 @@ import type { AIPrompt, AICompletion } from "@/types/ai";
import { showToast } from "@/utils/toast"; import { showToast } from "@/utils/toast";
import { formatDate } from "@/utils/format-date"; import { formatDate } from "@/utils/format-date";
import { import {
Play,
CheckCircle2, CheckCircle2,
Clock, Clock,
DollarSign, DollarSign,
AlertTriangle, AlertTriangle,
ChevronRight,
ChevronDown,
Terminal, Terminal,
MessageSquare, MessageSquare,
Sparkles, Sparkles,
@ -33,6 +28,7 @@ import {
Activity Activity
} from "lucide-react"; } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import CodeBadge from "@/components/shared/CodeBadge";
const PromptExecutions = (): ReactElement => { const PromptExecutions = (): ReactElement => {
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>();
@ -112,7 +108,9 @@ const PromptExecutions = (): ReactElement => {
const promptVersion = metadata.prompt_version || "—"; const promptVersion = metadata.prompt_version || "—";
return ( return (
<div className="bg-[#f8fafc] border border-gray-150 rounded-lg p-5 text-xs text-[#334155] space-y-4 shadow-inner"> <>
{/* <div className="bg-[#f8fafc] border border-gray-150 rounded-lg p-5 text-xs text-[#334155] space-y-4 shadow-inner"> */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{/* Left Column: Metadata & Input Variables */} {/* Left Column: Metadata & Input Variables */}
<div className="space-y-3"> <div className="space-y-3">
@ -240,37 +238,38 @@ const PromptExecutions = (): ReactElement => {
</div> </div>
)} )}
</div> </div>
</div> {/* </div> */}
</>
); );
}; };
const columns: Column<AICompletion>[] = [ const columns: Column<AICompletion>[] = [
{ // {
key: "expand", // key: "expand",
label: "", // label: "",
width: "40px", // width: "40px",
render: (row) => ( // render: (row) => (
<button // <button
type="button" // type="button"
onClick={(e) => { // onClick={(e) => {
e.stopPropagation(); // e.stopPropagation();
toggleExpand(row.id); // toggleExpand(row.id);
}} // }}
className="text-gray-400 hover:text-[#112868] transition-colors" // className="text-gray-400 hover:text-[#112868] transition-colors"
> // >
{expandedId === row.id ? ( // {expandedId === row.id ? (
<ChevronDown className="w-4 h-4" /> // <ChevronDown className="w-4 h-4" />
) : ( // ) : (
<ChevronRight className="w-4 h-4" /> // <ChevronRight className="w-4 h-4" />
)} // )}
</button> // </button>
), // ),
}, // },
{ {
key: "date", key: "date",
label: "Date", label: "Date",
render: (row) => ( render: (row) => (
<span className="whitespace-nowrap font-medium text-gray-700"> <span className="whitespace-nowrap">
{formatDate(row.created_at || "")} {formatDate(row.created_at || "")}
</span> </span>
), ),
@ -279,16 +278,14 @@ const PromptExecutions = (): ReactElement => {
key: "provider", key: "provider",
label: "Provider", label: "Provider",
render: (row) => ( render: (row) => (
<span className="inline-flex items-center rounded bg-gray-50 border border-gray-150 px-2 py-0.5 text-xs font-medium text-gray-600"> <CodeBadge label={row.provider} />
{row.provider}
</span>
), ),
}, },
{ {
key: "model", key: "model",
label: "Model", label: "Model",
render: (row) => ( render: (row) => (
<span className="font-mono text-xs text-gray-500 line-clamp-1 max-w-[150px]" title={row.model}> <span className="font-mono line-clamp-1 max-w-[150px]" title={row.model}>
{row.model} {row.model}
</span> </span>
), ),
@ -297,7 +294,7 @@ const PromptExecutions = (): ReactElement => {
key: "latency", key: "latency",
label: "Latency", label: "Latency",
render: (row) => ( render: (row) => (
<span className="font-medium text-gray-600"> <span>
{row.latency_ms ? `${row.latency_ms}ms` : "—"} {row.latency_ms ? `${row.latency_ms}ms` : "—"}
</span> </span>
), ),
@ -306,7 +303,7 @@ const PromptExecutions = (): ReactElement => {
key: "cost", key: "cost",
label: "Cost", label: "Cost",
render: (row) => ( render: (row) => (
<span className="font-semibold text-gray-600 text-xs"> <span>
{row.cost ? `USD ${row.cost.toFixed(5)}` : "—"} {row.cost ? `USD ${row.cost.toFixed(5)}` : "—"}
</span> </span>
), ),
@ -359,17 +356,17 @@ const PromptExecutions = (): ReactElement => {
</div> </div>
), ),
description: `Track execution metrics, variables, and failure traces for prompt "${prompt?.name}".`, description: `Track execution metrics, variables, and failure traces for prompt "${prompt?.name}".`,
action: ( // action: (
<div className="flex gap-2"> // <div className="flex gap-2">
<SecondaryButton onClick={() => navigate("/tenant/ai/prompts")}> // <SecondaryButton onClick={() => navigate("/tenant/ai/prompts")}>
Back to Prompts // Back to Prompts
</SecondaryButton> // </SecondaryButton>
<PrimaryButton onClick={() => navigate(`/tenant/ai/prompts/${id}/execute`)}> // <PrimaryButton onClick={() => navigate(`/tenant/ai/prompts/${id}/execute`)}>
<Play className="w-4 h-4 mr-1.5 inline shrink-0 text-white" /> // <Play className="w-4 h-4 mr-1.5 inline shrink-0 text-white" />
Execute Prompt // Execute Prompt
</PrimaryButton> // </PrimaryButton>
</div> // </div>
), // ),
}} }}
> >
<div className="flex items-start gap-6"> <div className="flex items-start gap-6">
@ -402,10 +399,10 @@ const PromptExecutions = (): ReactElement => {
</div> </div>
{/* FILTER AND DATA TABLE */} {/* FILTER AND DATA TABLE */}
<div className="bg-white border border-gray-300 rounded-lg shadow-sm p-4 space-y-4"> <div className="bg-white border border-gray-300 rounded-lg shadow-sm p-2 space-y-4">
{/* FILTERS BAR */} {/* FILTERS BAR */}
<div className="flex items-center justify-between border-b border-gray-150 pb-3"> <div className="flex items-center justify-between">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<FilterDropdown <FilterDropdown
label="Status" label="Status"
@ -430,7 +427,7 @@ const PromptExecutions = (): ReactElement => {
</div> </div>
{/* DATA TABLE */} {/* DATA TABLE */}
<div className="overflow-hidden border border-gray-200 rounded-lg shadow-sm"> <div className="overflow-hidden">
<DataTable <DataTable
data={executions} data={executions}
columns={columns} columns={columns}
@ -445,7 +442,7 @@ const PromptExecutions = (): ReactElement => {
/> />
{pagination.total > 0 && ( {pagination.total > 0 && (
<div className="border-t border-gray-200 px-5 py-4 bg-gray-50/50"> // <div className="border-t border-gray-200 px-5 py-4 bg-gray-50/50">
<Pagination <Pagination
currentPage={pagination.page} currentPage={pagination.page}
totalPages={pagination.totalPages} totalPages={pagination.totalPages}
@ -462,7 +459,7 @@ const PromptExecutions = (): ReactElement => {
{ value: "20", label: "20 per page" }, { value: "20", label: "20 per page" },
]} ]}
/> />
</div> // </div>
)} )}
</div> </div>
</div> </div>