feat: add PromptExecutions detail page with execution monitoring and metrics tracking
This commit is contained in:
parent
b6e594611e
commit
9415e9e9bf
@ -8,8 +8,6 @@ import {
|
||||
Pagination,
|
||||
FilterDropdown,
|
||||
GradientStatCard,
|
||||
PrimaryButton,
|
||||
SecondaryButton,
|
||||
MarkdownViewer,
|
||||
} from "@/components/shared";
|
||||
import { aiService } from "@/services/ai-service";
|
||||
@ -17,13 +15,10 @@ import type { AIPrompt, AICompletion } from "@/types/ai";
|
||||
import { showToast } from "@/utils/toast";
|
||||
import { formatDate } from "@/utils/format-date";
|
||||
import {
|
||||
Play,
|
||||
CheckCircle2,
|
||||
Clock,
|
||||
DollarSign,
|
||||
AlertTriangle,
|
||||
ChevronRight,
|
||||
ChevronDown,
|
||||
Terminal,
|
||||
MessageSquare,
|
||||
Sparkles,
|
||||
@ -33,6 +28,7 @@ import {
|
||||
Activity
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import CodeBadge from "@/components/shared/CodeBadge";
|
||||
|
||||
const PromptExecutions = (): ReactElement => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
@ -112,7 +108,9 @@ const PromptExecutions = (): ReactElement => {
|
||||
const promptVersion = metadata.prompt_version || "—";
|
||||
|
||||
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">
|
||||
{/* Left Column: Metadata & Input Variables */}
|
||||
<div className="space-y-3">
|
||||
@ -240,37 +238,38 @@ const PromptExecutions = (): ReactElement => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* </div> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const columns: Column<AICompletion>[] = [
|
||||
{
|
||||
key: "expand",
|
||||
label: "",
|
||||
width: "40px",
|
||||
render: (row) => (
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
toggleExpand(row.id);
|
||||
}}
|
||||
className="text-gray-400 hover:text-[#112868] transition-colors"
|
||||
>
|
||||
{expandedId === row.id ? (
|
||||
<ChevronDown className="w-4 h-4" />
|
||||
) : (
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
)}
|
||||
</button>
|
||||
),
|
||||
},
|
||||
// {
|
||||
// key: "expand",
|
||||
// label: "",
|
||||
// width: "40px",
|
||||
// render: (row) => (
|
||||
// <button
|
||||
// type="button"
|
||||
// onClick={(e) => {
|
||||
// e.stopPropagation();
|
||||
// toggleExpand(row.id);
|
||||
// }}
|
||||
// className="text-gray-400 hover:text-[#112868] transition-colors"
|
||||
// >
|
||||
// {expandedId === row.id ? (
|
||||
// <ChevronDown className="w-4 h-4" />
|
||||
// ) : (
|
||||
// <ChevronRight className="w-4 h-4" />
|
||||
// )}
|
||||
// </button>
|
||||
// ),
|
||||
// },
|
||||
{
|
||||
key: "date",
|
||||
label: "Date",
|
||||
render: (row) => (
|
||||
<span className="whitespace-nowrap font-medium text-gray-700">
|
||||
<span className="whitespace-nowrap">
|
||||
{formatDate(row.created_at || "")}
|
||||
</span>
|
||||
),
|
||||
@ -279,16 +278,14 @@ const PromptExecutions = (): ReactElement => {
|
||||
key: "provider",
|
||||
label: "Provider",
|
||||
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">
|
||||
{row.provider}
|
||||
</span>
|
||||
<CodeBadge label={row.provider} />
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "model",
|
||||
label: "Model",
|
||||
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}
|
||||
</span>
|
||||
),
|
||||
@ -297,7 +294,7 @@ const PromptExecutions = (): ReactElement => {
|
||||
key: "latency",
|
||||
label: "Latency",
|
||||
render: (row) => (
|
||||
<span className="font-medium text-gray-600">
|
||||
<span>
|
||||
{row.latency_ms ? `${row.latency_ms}ms` : "—"}
|
||||
</span>
|
||||
),
|
||||
@ -306,7 +303,7 @@ const PromptExecutions = (): ReactElement => {
|
||||
key: "cost",
|
||||
label: "Cost",
|
||||
render: (row) => (
|
||||
<span className="font-semibold text-gray-600 text-xs">
|
||||
<span>
|
||||
{row.cost ? `USD ${row.cost.toFixed(5)}` : "—"}
|
||||
</span>
|
||||
),
|
||||
@ -359,17 +356,17 @@ const PromptExecutions = (): ReactElement => {
|
||||
</div>
|
||||
),
|
||||
description: `Track execution metrics, variables, and failure traces for prompt "${prompt?.name}".`,
|
||||
action: (
|
||||
<div className="flex gap-2">
|
||||
<SecondaryButton onClick={() => navigate("/tenant/ai/prompts")}>
|
||||
Back to Prompts
|
||||
</SecondaryButton>
|
||||
<PrimaryButton onClick={() => navigate(`/tenant/ai/prompts/${id}/execute`)}>
|
||||
<Play className="w-4 h-4 mr-1.5 inline shrink-0 text-white" />
|
||||
Execute Prompt
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
),
|
||||
// action: (
|
||||
// <div className="flex gap-2">
|
||||
// <SecondaryButton onClick={() => navigate("/tenant/ai/prompts")}>
|
||||
// Back to Prompts
|
||||
// </SecondaryButton>
|
||||
// <PrimaryButton onClick={() => navigate(`/tenant/ai/prompts/${id}/execute`)}>
|
||||
// <Play className="w-4 h-4 mr-1.5 inline shrink-0 text-white" />
|
||||
// Execute Prompt
|
||||
// </PrimaryButton>
|
||||
// </div>
|
||||
// ),
|
||||
}}
|
||||
>
|
||||
<div className="flex items-start gap-6">
|
||||
@ -402,10 +399,10 @@ const PromptExecutions = (): ReactElement => {
|
||||
</div>
|
||||
|
||||
{/* 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 */}
|
||||
<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">
|
||||
<FilterDropdown
|
||||
label="Status"
|
||||
@ -430,7 +427,7 @@ const PromptExecutions = (): ReactElement => {
|
||||
</div>
|
||||
|
||||
{/* DATA TABLE */}
|
||||
<div className="overflow-hidden border border-gray-200 rounded-lg shadow-sm">
|
||||
<div className="overflow-hidden">
|
||||
<DataTable
|
||||
data={executions}
|
||||
columns={columns}
|
||||
@ -445,7 +442,7 @@ const PromptExecutions = (): ReactElement => {
|
||||
/>
|
||||
|
||||
{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
|
||||
currentPage={pagination.page}
|
||||
totalPages={pagination.totalPages}
|
||||
@ -462,7 +459,7 @@ const PromptExecutions = (): ReactElement => {
|
||||
{ value: "20", label: "20 per page" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
// </div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user