import { apiRequest } from "@/shared/api/client"; import { createObjectDecoder, hasShape, isArrayOf, isNumber, isOneOf, isOptional, isString } from "@/shared/api/decoder"; import type { PeriodValue } from "@/shared/lib/period"; export type DashboardPeriod = PeriodValue; export type DashboardUsageDTO = { requests: number; successfulRequests: number; failedRequests: number; inputTokens: number; cachedInputTokens: number; outputTokens: number; reasoningTokens: number; tokens: number; billedCostUsdTicks: number; successRate: number; averageFirstTokenMs?: number; outputTokensPerSecond?: number; firstTokenSamples?: number; throughputSamples?: number; }; export type DashboardDTO = { period: DashboardPeriod; generatedAt: string; range: { start: string; end: string }; resources: { activeAccounts: number; totalAccounts: number; buildAccounts: number; webAccounts: number; consoleAccounts: number; enabledModels: number; totalModels: number; activeClientKeys: number; totalClientKeys: number; }; usage: DashboardUsageDTO; series: Array<{ start: string; end: string; requests: number; inputTokens: number; cachedInputTokens: number; outputTokens: number; reasoningTokens: number; tokens: number; billedCostUsdTicks: number }>; activity: Array<{ start: string; requests: number }>; topModels: Array<{ model: string; requests: number; inputTokens: number; cachedInputTokens: number; outputTokens: number; reasoningTokens: number; tokens: number; billedCostUsdTicks: number }>; providers: Array<{ provider: string; requests: number; successfulRequests: number; tokens: number }>; }; const dashboardSeriesItem = hasShape({ start: isString, end: isString, requests: isNumber, inputTokens: isNumber, cachedInputTokens: isNumber, outputTokens: isNumber, reasoningTokens: isNumber, tokens: isNumber, billedCostUsdTicks: isNumber, }); const dashboardUsage = hasShape({ requests: isNumber, successfulRequests: isNumber, failedRequests: isNumber, inputTokens: isNumber, cachedInputTokens: isNumber, outputTokens: isNumber, reasoningTokens: isNumber, tokens: isNumber, billedCostUsdTicks: isNumber, successRate: isNumber, averageFirstTokenMs: isOptional(isNumber), outputTokensPerSecond: isOptional(isNumber), firstTokenSamples: isOptional(isNumber), throughputSamples: isOptional(isNumber), }); const dashboardModelItem = hasShape({ model: isString, requests: isNumber, inputTokens: isNumber, cachedInputTokens: isNumber, outputTokens: isNumber, reasoningTokens: isNumber, tokens: isNumber, billedCostUsdTicks: isNumber, }); const decodeDashboard = createObjectDecoder("dashboard", { period: isOneOf("24h", "7d", "30d", "90d"), generatedAt: isString, range: hasShape({ start: isString, end: isString }), resources: hasShape({ activeAccounts: isNumber, totalAccounts: isNumber, buildAccounts: isNumber, webAccounts: isNumber, consoleAccounts: isNumber, enabledModels: isNumber, totalModels: isNumber, activeClientKeys: isNumber, totalClientKeys: isNumber, }), usage: dashboardUsage, series: isArrayOf(dashboardSeriesItem), activity: isArrayOf(hasShape({ start: isString, requests: isNumber })), topModels: isArrayOf(dashboardModelItem), providers: isArrayOf(hasShape({ provider: isString, requests: isNumber, successfulRequests: isNumber, tokens: isNumber })), }); export function getDashboard(period: DashboardPeriod, timezone: string, refresh = false): Promise { const query = new URLSearchParams({ period, timezone }); if (refresh) query.set("refresh", "1"); return apiRequest(`/api/admin/v1/dashboard?${query.toString()}`, {}, decodeDashboard); }