import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Label } from "@/components/ui/label";
import { Progress } from "@/components/ui/progress";
import { DottedSeparator } from "@/components/ui/separator";
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from "@/components/ui/sheet";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { ProviderIconType, RenderProviderIcon } from "@/lib/constants/icons";
import { ProviderLabels, ProviderName } from "@/lib/constants/logs";
import { VirtualKey } from "@/lib/types/governance";
import { cn } from "@/lib/utils";
import { calculateUsagePercentage, formatCurrency, parseResetPeriod } from "@/lib/utils/governance";
import { formatDistanceToNow } from "date-fns";
import { Lock, Users } from "lucide-react";
import { useVirtualKeyUsage } from "../hooks/useVirtualKeyUsage";
function usageBarClass(pct: number, exhausted: boolean) {
if (exhausted) return "[&>div]:bg-red-500/70";
if (pct > 80) return "[&>div]:bg-amber-500/70";
return "[&>div]:bg-emerald-500/70";
}
function UsageLine({ current, max, format }: { current: number; max: number; format: (n: number) => string }) {
const pct = calculateUsagePercentage(current, max);
const exhausted = max > 0 && current >= max;
return (
{format(current)} / {format(max)}
80 ? "text-amber-500" : "text-muted-foreground")}>
{pct}%
);
}
interface VirtualKeyDetailSheetProps {
virtualKey: VirtualKey;
onClose: () => void;
}
export default function VirtualKeyDetailSheet({ virtualKey, onClose }: VirtualKeyDetailSheetProps) {
const { assignedUsers, isManagedByProfile, managingProfile, hasApRateLimit, displayBudgets, displayRateLimit } =
useVirtualKeyUsage(virtualKey);
const getEntityInfo = () => {
if (virtualKey.team) {
return { type: "Team", name: virtualKey.team.name };
}
if (virtualKey.customer) {
return { type: "Customer", name: virtualKey.customer.name };
}
return { type: "None", name: "" };
};
const entityInfo = getEntityInfo();
const isExhausted =
// Budget exhausted (AP-mirrored when managed, VK-own otherwise)
displayBudgets?.some((b) => b.current_usage >= b.max_limit) ||
// Rate limits exhausted
(displayRateLimit?.token_current_usage &&
displayRateLimit?.token_max_limit &&
displayRateLimit.token_current_usage >= displayRateLimit.token_max_limit) ||
(displayRateLimit?.request_current_usage &&
displayRateLimit?.request_max_limit &&
displayRateLimit.request_current_usage >= displayRateLimit.request_max_limit);
return (
{virtualKey.name}
{virtualKey.description || "Virtual key details and usage information"}
{isManagedByProfile ? (
This virtual key is managed by an access profile. You can rename it or update its description from the edit button, but
providers, budgets, rate limits, and MCP access are controlled by the profile and must be changed there.
) : null}
{assignedUsers.length > 0 ? (
Assigned Users
{assignedUsers.map((u) => u.name || u.email).join(", ")}
) : null}
{/* Basic Information */}
Basic Information
Status
{virtualKey.is_active ? (isExhausted ? "Exhausted" : "Active") : "Inactive"}
Created
{formatDistanceToNow(new Date(virtualKey.created_at), { addSuffix: true })}
Last Updated
{formatDistanceToNow(new Date(virtualKey.updated_at), { addSuffix: true })}
{entityInfo.type !== "None" && (
Assigned To
{entityInfo.type}
{entityInfo.name}
)}
{/* Provider Configurations */}
Provider Configurations
{!virtualKey.provider_configs || virtualKey.provider_configs.length === 0 ? (
No providers configured (deny-by-default)
) : (
{virtualKey.provider_configs.map((config, index) => (
{/* Provider Header */}
{ProviderLabels[config.provider as ProviderName] || config.provider}
Weight: {config.weight}
{/* Basic Config */}
Allowed Models
{config.allowed_models?.includes("*") ? (
All Models
) : config.allowed_models && config.allowed_models.length > 0 ? (
{config.allowed_models.map((model) => (
{model}
))}
) : (
No models (deny all)
)}
Allowed Keys
{config.allow_all_keys ? (
All Keys
) : config.keys && config.keys.length > 0 ? (
{config.keys.map((key) => (
{key.name}
))}
) : (
No keys (deny all)
)}
{/* Provider Budgets */}
{config.budgets && config.budgets.length > 0 && (
<>
Provider Budgets
{config.budgets.map((b, bIdx) => (
Resets {parseResetPeriod(b.reset_duration)}
{virtualKey.calendar_aligned && " (calendar)"}
{b.last_reset ? (
Last reset {formatDistanceToNow(new Date(b.last_reset), { addSuffix: true })}
) : null}
))}
>
)}
{/* Provider Rate Limits */}
{config.rate_limit && (
<>
Provider Rate Limits
{/* Token Limits */}
{config.rate_limit.token_max_limit != null ? (
TOKEN LIMITS
n.toLocaleString()}
/>
Resets {parseResetPeriod(config.rate_limit.token_reset_duration || "")}
{config.rate_limit.token_last_reset ? (
Last reset {formatDistanceToNow(new Date(config.rate_limit.token_last_reset), { addSuffix: true })}
) : null}
) : null}
{/* Request Limits */}
{config.rate_limit.request_max_limit != null ? (
REQUEST LIMITS
n.toLocaleString()}
/>
Resets {parseResetPeriod(config.rate_limit.request_reset_duration || "")}
{config.rate_limit.request_last_reset ? (
Last reset {formatDistanceToNow(new Date(config.rate_limit.request_last_reset), { addSuffix: true })}
) : null}
) : null}
{config.rate_limit.token_max_limit == null && config.rate_limit.request_max_limit == null && (
No rate limits configured for this provider
)}
>
)}
))}
)}
{/* MCP Client Configurations */}
MCP Client Configurations
{!virtualKey.mcp_configs || virtualKey.mcp_configs.length === 0 ? (
No MCP clients configured (deny-by-default)
) : (
MCP Client
Allowed Tools
{virtualKey.mcp_configs.map((config, index) => (
{config.mcp_client?.name || "Unknown Client"}
{config.tools_to_execute?.includes("*") ? (
All Tools
) : config.tools_to_execute && config.tools_to_execute.length > 0 ? (
{config.tools_to_execute.map((tool) => (
{tool}
))}
) : (
No tools (deny all)
)}
))}
)}
{/* Budget Information */}
Budget Information
{isManagedByProfile && managingProfile?.budgets?.length ? (
(from {managingProfile.name})
) : null}
{displayBudgets && displayBudgets.length > 0 ? (
{displayBudgets.map((b, bIdx) => (
Resets {parseResetPeriod(b.reset_duration)}
{virtualKey.calendar_aligned && " (calendar)"}
{b.last_reset ? (
Last reset {formatDistanceToNow(new Date(b.last_reset), { addSuffix: true })}
) : null}
))}
) : (
No budget limits configured
)}
{/* Rate Limits */}
Rate Limits
{isManagedByProfile && hasApRateLimit ? (
(from {managingProfile?.name})
) : null}
{displayRateLimit ? (
{/* Token Limits */}
{displayRateLimit.token_max_limit != null ? (
Token Limits
n.toLocaleString()}
/>
Resets {parseResetPeriod(displayRateLimit.token_reset_duration || "")}
{displayRateLimit.token_last_reset ? (
Last reset {formatDistanceToNow(new Date(displayRateLimit.token_last_reset), { addSuffix: true })}
) : null}
) : null}
{/* Request Limits */}
{displayRateLimit.request_max_limit != null ? (
Request Limits
n.toLocaleString()}
/>
Resets {parseResetPeriod(displayRateLimit.request_reset_duration || "")}
{displayRateLimit.request_last_reset ? (
Last reset {formatDistanceToNow(new Date(displayRateLimit.request_last_reset), { addSuffix: true })}
) : null}
) : null}
{displayRateLimit.token_max_limit == null && displayRateLimit.request_max_limit == null && (
No rate limits configured
)}
) : (
No rate limits configured
)}
);
}