| import { apiRequest } from "@/shared/api/client"; |
| import { createObjectDecoder, hasShape, isArrayOf, isBoolean, isNumber, isOneOf, isOptional, isRecordOf, isString } from "@/shared/api/decoder"; |
| import type { PeriodValue } from "@/shared/lib/period"; |
| import type { SortOrder } from "@/shared/lib/table-sort"; |
|
|
| export type AuditPeriod = PeriodValue; |
|
|
| export type AuditBillingComponentDTO = { |
| kind: "uncached_input" | "cached_input" | "output" | "input_image" | "output_image" | "output_second"; |
| unit: "token" | "image" | "second"; |
| quantity: number; |
| unitPriceInUsdTicks: number; |
| subtotalInUsdTicks: number; |
| }; |
|
|
| export type AuditBillingBreakdownDTO = { |
| source: "upstream" | "official"; |
| method: "upstream_reported" | "official_rates" | "stored_estimate"; |
| model?: string; |
| version?: string; |
| tier?: "standard" | "long_context" | "media"; |
| components: AuditBillingComponentDTO[]; |
| totalInUsdTicks: number; |
| }; |
|
|
| export type AuditDTO = { |
| id: string; |
| requestId: string; |
| clientKeyId: string; |
| clientKeyName?: string; |
| modelRouteId: string; |
| modelPublicId?: string; |
| modelUpstreamModel?: string; |
| provider: "grok_build" | "grok_web" | "grok_console"; |
| operation: "responses" | "compaction" | "chat" | "messages" | "image" | "image_edit" | "video"; |
| usageSource: "upstream" | "estimated" | "none"; |
| accountId?: string; |
| accountName?: string; |
| egressNodeId?: string; |
| egressNodeName?: string; |
| egressScope?: "grok_build" | "grok_web" | "grok_console" | "grok_web_asset"; |
| egressMode?: "direct" | "proxy"; |
| statusCode: number; |
| streaming: boolean; |
| mediaInputImages: number; |
| mediaOutputImages: number; |
| mediaOutputSeconds: number; |
| inputTokens: number; |
| cachedInputTokens: number; |
| outputTokens: number; |
| reasoningTokens: number; |
| totalTokens: number; |
| costInUsdTicks: number; |
| estimatedCostInUsdTicks: number; |
| pricingModel?: string; |
| pricingVersion?: string; |
| billing?: AuditBillingBreakdownDTO; |
| numSourcesUsed: number; |
| numServerSideToolsUsed: number; |
| contextInputTokens: number; |
| contextOutputTokens: number; |
| firstTokenMs?: number; |
| outputTokensPerSecond?: number; |
| durationMs: number; |
| errorCode?: string; |
| attemptCount: number; |
| createdAt: string; |
| }; |
|
|
| export type AuditAttemptDTO = { |
| id: string; |
| number: number; |
| source: "upstream_http" | "gateway_transport" | "credential"; |
| stage: string; |
| accountId?: string; |
| accountName?: string; |
| method?: string; |
| requestPath?: string; |
| upstreamUrl?: string; |
| startedAt: string; |
| durationMs: number; |
| upstreamStatusCode?: number; |
| upstreamStatus?: string; |
| responseHeaders: Record<string, string[]>; |
| responseBody: string; |
| responseBodyEncoding: "utf8" | "base64"; |
| responseBodyTruncated: boolean; |
| transportError?: string; |
| errorChain: Array<{ type: string; message: string }>; |
| }; |
|
|
| export type AuditDetailDTO = { |
| audit: AuditDTO; |
| attempts: AuditAttemptDTO[]; |
| }; |
|
|
| export type AuditCursorPageDTO = { |
| items: AuditDTO[]; |
| pageSize: number; |
| nextCursor: string; |
| hasMore: boolean; |
| }; |
|
|
| export type AuditSummaryDTO = { |
| period: AuditPeriod; |
| generatedAt: string; |
| range: { start: string; end: string }; |
| usage: { |
| requests: number; |
| successfulRequests: number; |
| failedRequests: number; |
| inputTokens: number; |
| cachedInputTokens: number; |
| outputTokens: number; |
| reasoningTokens: number; |
| totalTokens: number; |
| averageDurationMs: number; |
| successRate: number; |
| estimatedCostInUsdTicks: number; |
| }; |
| pricing: { |
| source: string; |
| asOf: string; |
| pricedRequests: number; |
| unpricedRequests: number; |
| pricedTokens: number; |
| unpricedTokens: number; |
| }; |
| }; |
|
|
| const auditBillingComponentValidator = hasShape({ |
| kind: isOneOf("uncached_input", "cached_input", "output", "input_image", "output_image", "output_second"), |
| unit: isOneOf("token", "image", "second"), quantity: isNumber, unitPriceInUsdTicks: isNumber, subtotalInUsdTicks: isNumber, |
| }); |
| const auditBillingValidator = hasShape({ |
| source: isOneOf("upstream", "official"), method: isOneOf("upstream_reported", "official_rates", "stored_estimate"), |
| model: isOptional(isString), version: isOptional(isString), tier: isOptional(isOneOf("standard", "long_context", "media")), |
| components: isArrayOf(auditBillingComponentValidator), totalInUsdTicks: isNumber, |
| }); |
| const auditValidator = hasShape({ |
| id: isString, requestId: isString, clientKeyId: isString, clientKeyName: isOptional(isString), modelRouteId: isString, |
| modelPublicId: isOptional(isString), modelUpstreamModel: isOptional(isString), provider: isOneOf("grok_build", "grok_web", "grok_console"), |
| operation: isOneOf("responses", "compaction", "chat", "messages", "image", "image_edit", "video"), usageSource: isOneOf("upstream", "estimated", "none"), |
| accountId: isOptional(isString), accountName: isOptional(isString), |
| egressNodeId: isOptional(isString), egressNodeName: isOptional(isString), |
| egressScope: isOptional(isOneOf("grok_build", "grok_web", "grok_console", "grok_web_asset")), egressMode: isOptional(isOneOf("direct", "proxy")), |
| statusCode: isNumber, streaming: isBoolean, |
| mediaInputImages: isNumber, mediaOutputImages: isNumber, mediaOutputSeconds: isNumber, inputTokens: isNumber, |
| cachedInputTokens: isNumber, outputTokens: isNumber, reasoningTokens: isNumber, totalTokens: isNumber, |
| costInUsdTicks: isNumber, estimatedCostInUsdTicks: isNumber, pricingModel: isOptional(isString), pricingVersion: isOptional(isString), billing: isOptional(auditBillingValidator), |
| numSourcesUsed: isNumber, numServerSideToolsUsed: isNumber, contextInputTokens: isNumber, contextOutputTokens: isNumber, |
| firstTokenMs: isOptional(isNumber), outputTokensPerSecond: isOptional(isNumber), |
| durationMs: isNumber, errorCode: isOptional(isString), attemptCount: isNumber, createdAt: isString, |
| }); |
| const auditAttemptValidator = hasShape({ |
| id: isString, number: isNumber, source: isOneOf("upstream_http", "gateway_transport", "credential"), stage: isString, |
| accountId: isOptional(isString), accountName: isOptional(isString), method: isOptional(isString), requestPath: isOptional(isString), upstreamUrl: isOptional(isString), |
| startedAt: isString, durationMs: isNumber, upstreamStatusCode: isOptional(isNumber), upstreamStatus: isOptional(isString), |
| responseHeaders: isRecordOf(isArrayOf(isString)), responseBody: isString, responseBodyEncoding: isOneOf("utf8", "base64"), responseBodyTruncated: isBoolean, |
| transportError: isOptional(isString), errorChain: isArrayOf(hasShape({ type: isString, message: isString })), |
| }); |
| const decodeAuditPage = createObjectDecoder<AuditCursorPageDTO>("audit page", { |
| items: isArrayOf(auditValidator), pageSize: isNumber, nextCursor: isString, hasMore: isBoolean, |
| }); |
| const decodeAuditSummary = createObjectDecoder<AuditSummaryDTO>("audit summary", { |
| period: isOneOf("24h", "7d", "30d", "90d"), generatedAt: isString, range: hasShape({ start: isString, end: isString }), |
| usage: hasShape({ |
| requests: isNumber, successfulRequests: isNumber, failedRequests: isNumber, inputTokens: isNumber, |
| cachedInputTokens: isNumber, outputTokens: isNumber, reasoningTokens: isNumber, totalTokens: isNumber, |
| averageDurationMs: isNumber, successRate: isNumber, estimatedCostInUsdTicks: isNumber, |
| }), |
| pricing: hasShape({ |
| source: isString, asOf: isString, pricedRequests: isNumber, unpricedRequests: isNumber, pricedTokens: isNumber, unpricedTokens: isNumber, |
| }), |
| }); |
| const decodeAuditDetail = createObjectDecoder<AuditDetailDTO>("audit detail", { |
| audit: auditValidator, |
| attempts: isArrayOf(auditAttemptValidator), |
| }); |
|
|
| type AuditQuery = { |
| cursor?: string; |
| pageSize?: number; |
| search?: string; |
| model?: string; |
| status?: string; |
| mode?: string; |
| key?: string; |
| account?: string; |
| period: AuditPeriod; |
| sortBy?: string; |
| sortOrder?: SortOrder; |
| }; |
|
|
| export function getRequestAudits(input: AuditQuery, signal?: AbortSignal): Promise<AuditCursorPageDTO> { |
| const query = new URLSearchParams({ pagination: "cursor", pageSize: String(input.pageSize ?? 50), period: input.period }); |
| if (input.cursor) query.set("cursor", input.cursor); |
| if (input.search) query.set("search", input.search); |
| if (input.model) query.set("model", input.model); |
| if (input.status) query.set("status", input.status); |
| if (input.mode) query.set("mode", input.mode); |
| if (input.key) query.set("key", input.key); |
| if (input.account) query.set("account", input.account); |
| if (input.sortBy && input.sortOrder) { |
| query.set("sortBy", input.sortBy); |
| query.set("sortOrder", input.sortOrder); |
| } |
| return apiRequest(`/api/admin/v1/request-audits?${query}`, { signal }, decodeAuditPage); |
| } |
|
|
| export function getRequestAuditSummary(input: Omit<AuditQuery, "cursor" | "pageSize">, refresh = false, signal?: AbortSignal): Promise<AuditSummaryDTO> { |
| const query = new URLSearchParams({ period: input.period }); |
| if (input.search) query.set("search", input.search); |
| if (input.model) query.set("model", input.model); |
| if (input.status) query.set("status", input.status); |
| if (input.mode) query.set("mode", input.mode); |
| if (input.key) query.set("key", input.key); |
| if (input.account) query.set("account", input.account); |
| if (refresh) query.set("refresh", "1"); |
| return apiRequest(`/api/admin/v1/request-audits/summary?${query}`, { signal }, decodeAuditSummary); |
| } |
|
|
| export function getRequestAudit(id: string, signal?: AbortSignal): Promise<AuditDetailDTO> { |
| return apiRequest(`/api/admin/v1/request-audits/${id}`, { signal }, decodeAuditDetail); |
| } |
|
|