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,
|
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>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user