import apiClient from './client' import type { GatewayMetricsSummary, AdminMonitoringResilienceStatus } from './monitoring' import type { ProviderPerformanceResponse } from './admin' export interface OverviewRange { from: string to: string timezone: string } export interface OverviewQuery extends OverviewRange { user_id?: string api_key_id?: string request_type?: string credential_owner_id?: string attribution_kind?: string model?: string provider_id?: string api_format?: string endpoint_kind?: string is_stream?: boolean has_format_conversion?: boolean slow_threshold_ms?: number status?: string search?: string account_status?: string usage_status?: string sort?: string order?: 'asc' | 'desc' group_by?: string amount_basis?: string granularity?: 'hour' | 'day' limit?: number offset?: number payment_limit?: number payment_offset?: number } export interface OverviewAmount { value: string | null currency: string basis: string status: 'known' | 'known_subtotal' | 'unknown' | 'estimated' | string } export interface OverviewMetrics { request_count: number successful_request_count: number failed_request_count: number cancelled_request_count: number in_flight_request_count: number unclassified_failure_count: number input_tokens: number | null output_tokens: number | null total_tokens: number | null usage_source?: 'reported' | 'estimated' | 'mixed' | 'unknown' usage_source_counts?: { reported: number; estimated: number; mixed: number; unknown: number } requests_per_second?: number requests_per_minute?: number tokens_per_minute?: number | null window_seconds?: number usage_active_users?: number enabled_users?: number success_rate: { value: number | null; numerator: number; denominator: number } latency_ms: { avg: number | null; p50: number | null; p95: number | null; p99: number | null; sample_count: number } rated_amount: OverviewAmount billable_amount: OverviewAmount quota_covered_amount: OverviewAmount wallet_consumed_amount: OverviewAmount wallet_debit_amount: OverviewAmount } export interface OverviewMeta { schema_version: number metric_version: string scope: { kind: string; user_id?: string } range: OverviewRange & { time_basis: string } generated_at: string data_through: string | null read_revision: string available_metrics?: string[] projection?: { projection_from: string | null projection_through: string | null dirty_bucket_count: number missing_bucket_count: number read_enabled: boolean } coverage: { status: string request_count: number usage_available_count: number pricing_available_count: number settled_count: number attribution_available_count?: number unrecoverable_bucket_count?: number } } export interface OverviewResponse { meta: OverviewMeta; data: T } export type OverviewDashboardTotals = Pick export interface OverviewDashboard { today: OverviewResponse total: OverviewResponse history_complete: boolean | null } export type OverviewDashboardTotal = { status: 'pending' } | { status: 'ready' total: OverviewResponse history_complete: boolean | null stale: boolean } export interface OverviewDashboardSummary { stats_since: string generated_at: string timezone: string activity_timezone?: string today_from: string window_seconds: number today: { request_count: number input_tokens: number | null output_tokens: number | null total_tokens: number | null billable_amount: OverviewAmount active_users: number cache_read_tokens: number | null cache_creation_tokens: number | null cache_input_tokens: number | null avg_first_byte_ms: number | null avg_response_ms: number | null stream_requests: number standard_requests: number } total: { request_count: number total_tokens: number | null billable_amount: OverviewAmount cache_read_tokens: number | null cache_input_tokens: number | null } users: { total: number; created_today: number; deleted_today: number } consecutive_active_days: number active_days: number activity_days: { date: string; requests: number }[] concurrency: { avg: number | null peak: number | null observed_from: string | null observed_through: string | null scope: 'node' coverage: 'partial' | 'complete' | 'unavailable' } } export interface OverviewPage { items: T[]; total: number; limit: number; offset: number } export interface OverviewSeriesPoint extends OverviewMetrics { bucket_start: string } export interface OverviewBreakdown extends OverviewMetrics { id: string | null; label: string | null } export interface OverviewDashboardCharts { summary: OverviewMetrics series: OverviewSeriesPoint[] models: (OverviewBreakdown & { bucket_start: string })[] providers: OverviewBreakdown[] } export interface OverviewEmployee extends OverviewMetrics { user_id: string username: string email: string | null is_active: boolean last_used_at: string | null active_days: number finance?: OverviewUserFinance | null } export interface OverviewUserFinance { wallet_balance: OverviewAmount recharge_balance: OverviewAmount gift_balance: OverviewAmount recharge_amount: OverviewAmount recharge_count: number plan_purchase_amount: OverviewAmount plan_purchase_count: number gift_credit_amount: OverviewAmount gift_credit_count: number balance_time_basis: 'current' payment_time_basis: 'credited_at' } export interface OverviewUserPayment { id: string order_no: string kind: 'wallet_recharge' | 'plan_purchase' | 'gift_credit' amount: OverviewAmount payment_method: string credited_at: string } export interface OverviewUsers extends OverviewPage { summary?: OverviewMetrics & { user_count: number; active_user_count: number } finance_summary?: OverviewUserFinance | null } export interface OverviewEmployeeDetail { user: { id: string; username: string; email: string | null; is_active: boolean } summary: OverviewMetrics finance?: OverviewUserFinance | null payments?: OverviewPage | null } export interface OverviewConsumption { id: string request_id: string started_at: string user_id: string | null model: string | null provider: string | null status: string settlement_status: string attribution_kind: string rated_amount: OverviewAmount billable_amount: OverviewAmount quota_covered_amount: OverviewAmount wallet_consumed_amount: OverviewAmount wallet_debit_amount: OverviewAmount } export interface OverviewCosts { summary: OverviewMetrics timeseries?: OverviewSeriesPoint[] supplier_estimated_cost: OverviewAmount supplier_verified_cost: OverviewAmount cache: { read_tokens: number | null; creation_tokens: number | null; read_cost: OverviewAmount; creation_cost: OverviewAmount; estimated_full_cost: OverviewAmount; estimated_savings: OverviewAmount; pricing_available_count?: number; request_count?: number } forecast: { amount: OverviewAmount; method: string; status: string; sample_days: number; period_end: string | null } } export interface OverviewExecutionActivity { observed_at: string observed_from: string window_seconds: number observed_window_seconds: number scope: { kind: 'node' } coverage: 'complete' | 'partial' providers: { provider_id: string; provider: string | null; requests_per_minute: number; current_concurrency: number }[] models: { model: string | null; requests_per_minute: number; current_concurrency: number }[] } export interface OverviewLive { observed_at: string | null window_seconds: number | null node_id: string | null scope: { kind: string; node_ids?: string[] } metrics?: GatewayMetricsSummary | null metrics_text?: string | null resilience: AdminMonitoringResilienceStatus | null unavailable_sections: string[] recent_activity?: OverviewResponse execution_activity?: OverviewExecutionActivity | null } export interface OverviewModelPerformance { model: string | null request_count: number success_count: number error_count: number success_rate: number | null avg_first_byte_time_ms: number | null avg_output_tps: number | null avg_response_time_ms: number | null } export interface OverviewPerformance { summary: OverviewMetrics timeseries: OverviewSeriesPoint[] providers: ProviderPerformanceResponse | null models?: OverviewModelPerformance[] errors: { reason: string; count: number }[] } async function get(path: string, params?: OverviewQuery, signal?: AbortSignal): Promise> { return (await apiClient.get>(`/api/admin/overview/${path}`, { params, signal })).data } export const overviewApi = { async dashboardSummary(timezone: string, signal?: AbortSignal): Promise { return (await apiClient.get('/api/admin/overview/dashboard/summary', { params: { timezone }, signal })).data }, async dashboard(timezone: string, signal?: AbortSignal): Promise { return (await apiClient.get('/api/admin/overview/dashboard', { params: { timezone }, signal })).data }, async dashboardTotal(timezone: string, signal?: AbortSignal): Promise { return (await apiClient.get('/api/admin/overview/dashboard/total', { params: { timezone }, signal })).data }, async dashboardCharts(range: OverviewRange, signal?: AbortSignal): Promise> { const { from, to, timezone } = range return (await apiClient.get>('/api/admin/overview/dashboard/charts', { params: { from, to, timezone, granularity: 'day' }, signal })).data }, summary: (query: OverviewQuery, signal?: AbortSignal) => get('summary', query, signal), timeseries: (query: OverviewQuery, signal?: AbortSignal) => get<{ items: OverviewSeriesPoint[]; granularity: string }>('timeseries', query, signal), breakdown: (query: OverviewQuery, signal?: AbortSignal) => get>('breakdown', query, signal), users: (query: OverviewQuery, signal?: AbortSignal) => get('users', query, signal), user: (id: string, query: OverviewQuery, signal?: AbortSignal) => get(`users/${encodeURIComponent(id)}`, query, signal), consumption: (query: OverviewQuery, signal?: AbortSignal) => get>('consumption', query, signal), costs: (query: OverviewQuery, signal?: AbortSignal) => get('costs', query, signal), performance: (query: OverviewQuery, signal?: AbortSignal) => get('operations/performance', query, signal), live: (signal?: AbortSignal) => get('operations/live', undefined, signal), resources: (signal?: AbortSignal) => get('operations/resources', undefined, signal), async exportCsv(path: 'users' | 'consumption' | 'breakdown', query: OverviewQuery, signal?: AbortSignal): Promise { const { limit: _limit, offset: _offset, ...filters } = query return (await apiClient.get(`/api/admin/overview/${path}`, { params: { ...filters, format: 'csv' }, responseType: 'blob', signal, })).data }, }