import 'server-only' import { fetchAdminBackend } from './backend-session' export interface SystemNodeHealth { id: string name: string category: 'stt' | 'llm' | 'voice_realtime' | 'rag_vector' | 'backend_api' | 'diarization' status: 'operational' | 'degraded' | 'offline' latencyMs: number uptimePercent: number versionOrModel: string vramOrMemory: string details: string } export interface PipelineStats { whisper: { engine: string; activeModel: string; avgLatencyMs: number; speedupFactor: string; partialStreamingFps: number; totalTranscriptionsToday: number; gpuVramUsage: string } ollama: { version: string; loadedModels: string[]; activeContextLimit: number; tokensPerSecond: number; vramAllocated: string; activeSessions: number } realtimeVoice: { backend: string; activeStreams: number; streamUptime: number; localFallbackRate: string; avgAudioRttMs: number } ragVector: { embeddingModel: string; indexedDocuments: number; totalVectorChunks: number; avgSearchLatencyMs: number; topHitRatePercent: number } meetingIntelligence: { diarizationEngine: string; speakerAccuracyPercent: number; activeMeetingSessions: number; templatesGeneratedToday: number; mindmapsExported: number } } export interface FeatureUsageBreakdown { featureId: string featureName: string category: string totalCalls?: number callCount?: number percentage?: number tokensUsed: number totalCost: number estimatedCostUsd?: number avgLatencyMs: number } export interface ServerStats { totalUsers: number activeUsersToday: number totalRequests: number totalCost: number serverUptimeSeconds: number errorCount: number arrUsd: number | null mrrUsd: number | null tierDistribution: { free: number; pro: number; pro_plus: number } | null nodes: SystemNodeHealth[] pipelines: PipelineStats | null featureBreakdown: FeatureUsageBreakdown[] recentErrors: Array<{ id: number; errorType: string; message: string; endpoint: string | null; createdAt: string }> } export interface UserItem { id: string uid: string email: string name: string role: 'user' | 'manager' | 'admin' | 'super_admin' tier: 'free' | 'pro' | 'pro_plus' | null createdAt: string lastLoginAt: string | null lastActiveDevice: string | null isActive: boolean dailyUsage: { dictations: number; dictationsMax: number | null; llmCalls: number; llmCallsMax: number | null; ragQueries: number; ragQueriesMax: number | null } | null } export interface ModelEndpoint { id: number modelId: string modelName: string provider: 'OpenAI' | 'Ollama Local' | 'Anthropic' | 'Local Sidecar' | 'DeepSeek' | 'Custom' endpointUrl: string apiKey: string costPer1kPromptTokens: number costPer1kCompletionTokens: number latencyMs?: number isActive: boolean isDefault?: boolean createdAt: string } export type STTProviderCategory = 'groq' | 'openai' | 'deepgram' | 'google' | 'assemblyai' | 'azure' | 'custom' | 'local-sidecar' export interface SttProviderEndpoint { id: number name: string providerType: STTProviderCategory endpointUrl: string apiKey: string modelId: string method: 'multipart' | 'binary-stream' | 'json-base64' | 'custom-rest' language: string prompt: string | null temperature: number costPerMinute: number costPerSecond: number isDefault: boolean isActive: boolean fallbackPriority: number extraHeadersJson: string | null latencyMs?: number createdAt: string updatedAt: string | null } export interface CreateSttEndpointDto { name: string providerType: STTProviderCategory endpointUrl: string apiKey?: string modelId: string method: string language?: string prompt?: string temperature?: number costPerMinute: number costPerSecond?: number isDefault?: boolean isActive?: boolean fallbackPriority?: number extraHeadersJson?: string memo: string } export type UpdateSttEndpointDto = CreateSttEndpointDto export interface SttTestResult { success: boolean message: string latencyMs: number transcriptPreview: string | null provider: string | null modelId: string | null } export interface SttUsageReport { totalTranscriptions: number totalAudioMinutes: number totalCost: number avgLatencyMs: number providerSummaries: Array<{ provider: string; modelId: string; totalRequests: number; totalAudioMinutes: number; totalCost: number; avgLatencyMs: number }> userSummaries: Array<{ userId: number; email: string; totalRequests: number; totalAudioMinutes: number; totalCost: number }> } export interface UsageReport { totalRequests: number totalPromptTokens: number totalCompletionTokens: number totalCost: number timeline: Array<{ date: string; dictations: number; meetingSummaries: number; aiChat: number; ragSearch: number; voiceRealtime: number; totalCost: number }> features: FeatureUsageBreakdown[] userSummaries: Array<{ userId: number; email: string; name?: string; tier?: string; totalRequests: number; totalTokens: number; totalCost: number }> modelSummaries: Array<{ modelId: string; modelName: string; provider?: string; totalRequests: number; totalTokens: number; totalCost: number }> } async function readJson(path: string): Promise { const response = await fetchAdminBackend(path) if (!response.ok) throw new Error(`Admin backend request failed (${response.status})`) try { return (await response.json()) as T } catch { throw new Error('Admin backend returned invalid JSON') } } function normalizeRole(value: unknown): UserItem['role'] { const normalized = typeof value === 'string' ? value.replace(/[_-]/g, '').toLowerCase() : '' if (normalized === 'superadmin') return 'super_admin' if (normalized === 'admin') return 'admin' if (normalized === 'manager') return 'manager' return 'user' } export async function fetchServerStats(): Promise { const data = await readJson>('/stats') if (typeof data.totalUsers !== 'number' || typeof data.activeUsersToday !== 'number' || typeof data.totalRequests !== 'number' || typeof data.totalCost !== 'number' || typeof data.serverUptimeSeconds !== 'number' || typeof data.errorCount !== 'number') { throw new Error('Admin stats response is incomplete') } return { totalUsers: data.totalUsers, activeUsersToday: data.activeUsersToday, totalRequests: data.totalRequests, totalCost: data.totalCost, serverUptimeSeconds: data.serverUptimeSeconds, errorCount: data.errorCount, arrUsd: typeof data.arrUsd === 'number' ? data.arrUsd : null, mrrUsd: typeof data.mrrUsd === 'number' ? data.mrrUsd : null, tierDistribution: data.tierDistribution ?? null, nodes: Array.isArray(data.nodes) ? data.nodes : [], pipelines: data.pipelines ?? null, featureBreakdown: Array.isArray(data.featureBreakdown) ? data.featureBreakdown : [], recentErrors: Array.isArray(data.recentErrors) ? data.recentErrors : [] } } export async function fetchUsers(): Promise { const data = await readJson>>('/users') if (!Array.isArray(data)) throw new Error('Admin users response is invalid') return data.map((item) => { if (typeof item.id !== 'number' || typeof item.email !== 'string' || typeof item.createdAt !== 'string') { throw new Error('Admin users response contains an invalid row') } return { id: String(item.id), uid: String(item.id), email: item.email, name: item.email, role: normalizeRole(item.role), tier: null, createdAt: item.createdAt, lastLoginAt: typeof item.lastLoginAt === 'string' ? item.lastLoginAt : null, lastActiveDevice: null, isActive: item.isActive === true, dailyUsage: null } }) } export async function fetchModelEndpoints(): Promise { const data = await readJson('/endpoints') if (!Array.isArray(data)) throw new Error('Model endpoints response is invalid') return data } export async function fetchSttEndpoints(): Promise { const data = await readJson('/stt-endpoints') if (!Array.isArray(data)) throw new Error('STT endpoints response is invalid') return data } export async function fetchSttUsageReport(): Promise { return readJson('/stt-usage') } export async function fetchUsageReport(): Promise { const data = await readJson & Partial>>('/usage') return { ...data, timeline: Array.isArray(data.timeline) ? data.timeline : [], features: Array.isArray(data.features) ? data.features : [] } }