@acarmisc/backstage-plugin-litellm 0.1.13 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/api.ts", "../src/components/DashboardHeader.tsx", "../src/components/KeysTable.tsx", "../src/components/UsageStats.tsx", "../src/components/TeamUsage.tsx", "../src/components/LiteLLMPage.tsx", "../src/plugin.ts", "../src/index.ts"],
4
- "sourcesContent": ["import { createApiRef, FetchApi } from '@backstage/core-plugin-api';\nimport {\n UserInfo,\n VirtualKey,\n ModelInfo,\n UsageMetrics,\n TeamInfo,\n GenerateKeyRequest,\n GenerateKeyResponse,\n UpdateKeyRequest,\n} from './types';\n\nclass ApiError extends Error {\n body: unknown;\n status: number;\n constructor(message: string, status: number, body: unknown) {\n super(message);\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface LiteLlmApiInterface {\n getUserInfo(): Promise<UserInfo>;\n listKeys(): Promise<VirtualKey[]>;\n generateKey(request: GenerateKeyRequest): Promise<GenerateKeyResponse>;\n updateKey(keyId: string, request: UpdateKeyRequest): Promise<VirtualKey>;\n deleteKey(keyId: string): Promise<{ success: boolean }>;\n listModels(): Promise<ModelInfo[]>;\n getTeams(): Promise<TeamInfo[]>;\n getUsage(startDate: string, endDate: string): Promise<UsageMetrics>;\n getTeamUsage(teamId: string, startDate: string, endDate: string): Promise<UsageMetrics>;\n}\n\nexport const liteLlmApiRef = createApiRef<LiteLlmApiInterface>({\n id: 'plugin.litellm.api',\n});\n\nexport class LiteLlmApi implements LiteLlmApiInterface {\n private fetchApi: FetchApi;\n private basePath: string;\n\n constructor(fetchApi: FetchApi, basePath: string = '/api/litellm') {\n this.fetchApi = fetchApi;\n this.basePath = basePath;\n }\n\n private async throwIfNotOk(response: Response): Promise<void> {\n if (!response.ok) {\n let body: unknown;\n try { body = await response.json(); } catch { body = await response.text().catch(() => ''); }\n throw new ApiError(`${response.status} ${response.statusText}`, response.status, body);\n }\n }\n\n private async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${this.basePath}${path}`, window.location.origin);\n if (params) {\n Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value));\n }\n const response = await this.fetchApi.fetch(url.toString());\n await this.throwIfNotOk(response);\n return response.json();\n }\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n const response = await this.fetchApi.fetch(`${this.basePath}${path}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n await this.throwIfNotOk(response);\n return response.json();\n }\n\n private async del<T>(path: string): Promise<T> {\n const response = await this.fetchApi.fetch(`${this.basePath}${path}`, {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n });\n await this.throwIfNotOk(response);\n return response.json();\n }\n\n // User identity is resolved server-side from the Backstage Bearer token.\n // No user_id param needed on the frontend.\n async getUserInfo(): Promise<UserInfo> {\n return this.get<UserInfo>('/user/info');\n }\n\n async listKeys(): Promise<VirtualKey[]> {\n return this.get<VirtualKey[]>('/keys');\n }\n\n async generateKey(request: GenerateKeyRequest): Promise<GenerateKeyResponse> {\n return this.post<GenerateKeyResponse>('/keys/generate', request);\n }\n\n async updateKey(keyId: string, request: UpdateKeyRequest): Promise<VirtualKey> {\n return this.post<VirtualKey>(`/keys/${encodeURIComponent(keyId)}/update`, request);\n }\n\n async deleteKey(keyId: string): Promise<{ success: boolean }> {\n return this.del<{ success: boolean }>(`/keys/${encodeURIComponent(keyId)}`);\n }\n\n async listModels(): Promise<ModelInfo[]> {\n return this.get<ModelInfo[]>('/models');\n }\n\n async getTeams(): Promise<TeamInfo[]> {\n return this.get<TeamInfo[]>('/teams');\n }\n\n async getUsage(startDate: string, endDate: string): Promise<UsageMetrics> {\n return this.get<UsageMetrics>('/usage', { start_date: startDate, end_date: endDate });\n }\n\n async getTeamUsage(teamId: string, startDate: string, endDate: string): Promise<UsageMetrics> {\n return this.get<UsageMetrics>(`/teams/${encodeURIComponent(teamId)}/usage`, {\n start_date: startDate,\n end_date: endDate,\n });\n }\n}\n", "import React from 'react';\nimport { Box, Typography, LinearProgress, Paper, Chip } from '@mui/material';\nimport { Warning } from '@mui/icons-material';\nimport { UserInfo, TeamInfo } from '../types';\n\ninterface DashboardHeaderProps {\n userInfo: UserInfo;\n teams: TeamInfo[];\n loading: boolean;\n}\n\nexport const DashboardHeader: React.FC<DashboardHeaderProps> = ({ userInfo, teams, loading }) => {\n if (loading) {\n return (\n <Paper sx={{ p: 2, mb: 2 }}>\n <LinearProgress />\n </Paper>\n );\n }\n\n const displayName = userInfo.user_email ?? userInfo.email ?? userInfo.user_id;\n const budget = userInfo.max_budget ?? 0;\n const spend = userInfo.spend ?? userInfo.current_spend ?? 0;\n const budgetPct = budget > 0 ? Math.min((spend / budget) * 100, 100) : 0;\n const isOver = budget > 0 && spend >= budget;\n const isNear = budget > 0 && spend >= budget * 0.8 && !isOver;\n\n return (\n <Paper sx={{ p: 2, mb: 2 }}>\n <Box display=\"flex\" alignItems=\"flex-start\" gap={2} flexWrap=\"wrap\">\n <Box flexGrow={1}>\n <Typography variant=\"h6\">{displayName}</Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {userInfo.user_id}\n </Typography>\n\n {teams.length > 0 && (\n <Box display=\"flex\" gap={0.75} flexWrap=\"wrap\" mt={1}>\n {teams.map(team => (\n <Chip\n key={team.team_id}\n label={team.team_alias || team.team_id}\n size=\"small\"\n variant=\"outlined\"\n color=\"primary\"\n />\n ))}\n </Box>\n )}\n </Box>\n\n {budget > 0 && (\n <Box minWidth={220}>\n <Box display=\"flex\" justifyContent=\"space-between\" mb={0.5}>\n <Typography variant=\"body2\">\n ${spend.toFixed(2)} / ${budget.toFixed(2)}\n </Typography>\n {isOver && <Chip icon={<Warning />} label=\"Over Budget\" size=\"small\" color=\"error\" />}\n {isNear && <Chip label=\"Near Limit\" size=\"small\" color=\"warning\" />}\n </Box>\n <LinearProgress\n variant=\"determinate\"\n value={budgetPct}\n color={isOver ? 'error' : isNear ? 'warning' : 'primary'}\n sx={{ height: 8, borderRadius: 1 }}\n />\n </Box>\n )}\n </Box>\n </Paper>\n );\n};\n", "import React, { useEffect, useState } from 'react';\nimport {\n Paper,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Button,\n IconButton,\n Box,\n Typography,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n TextField,\n MenuItem,\n Chip,\n CircularProgress,\n Autocomplete,\n} from '@mui/material';\nimport { ContentCopy, Delete, Add, Edit, Visibility, VisibilityOff } from '@mui/icons-material';\nimport {\n VirtualKey,\n ModelInfo,\n TeamInfo,\n GenerateKeyRequest,\n GenerateKeyResponse,\n UpdateKeyRequest,\n} from '../types';\n\ninterface KeysTableProps {\n keys: VirtualKey[];\n models: ModelInfo[];\n teams: TeamInfo[];\n loading: boolean;\n onGenerateKey: (request: GenerateKeyRequest) => Promise<GenerateKeyResponse>;\n onUpdateKey: (keyId: string, request: UpdateKeyRequest) => Promise<void>;\n onDeleteKey: (keyId: string) => Promise<void>;\n}\n\nconst maskKey = (key: string): string => {\n if (key.length <= 8) return '***';\n return `${key.slice(0, 4)}...${key.slice(-4)}`;\n};\n\nconst formatDate = (dateStr: string): string => {\n try {\n return new Date(dateStr).toLocaleDateString();\n } catch {\n return dateStr;\n }\n};\n\nconst emptyForm = (): GenerateKeyRequest => ({\n alias: '',\n models: [],\n duration: '30d',\n max_budget: undefined,\n tpm_limit: undefined,\n team_id: undefined,\n key_type: 'llm_api',\n});\n\nconst keyToEditForm = (k: VirtualKey): UpdateKeyRequest => ({\n key_alias: k.key_alias ?? '',\n models: k.models ?? [],\n max_budget: k.max_budget,\n tpm_limit: k.tpm_limit,\n rpm_limit: k.rpm_limit,\n});\n\nexport const KeysTable: React.FC<KeysTableProps> = ({\n keys,\n models,\n teams,\n loading,\n onGenerateKey,\n onUpdateKey,\n onDeleteKey,\n}) => {\n const [generateModalOpen, setGenerateModalOpen] = useState(false);\n const [showKeyValue, setShowKeyValue] = useState<string | null>(null);\n const [newKeyValue, setNewKeyValue] = useState<string | null>(null);\n const [formData, setFormData] = useState<GenerateKeyRequest>(emptyForm());\n const [submitting, setSubmitting] = useState(false);\n\n // Default to the user's first team when the modal opens so users in exactly\n // one team don't need to pick. Multi-team users see the picker pre-filled\n // and can change it. Teams are already filtered to the current user upstream.\n useEffect(() => {\n if (!generateModalOpen) return;\n if (!formData.team_id && teams.length > 0) {\n setFormData(f => ({ ...f, team_id: teams[0].team_id }));\n }\n }, [generateModalOpen, teams, formData.team_id]);\n\n const teamRequired = teams.length > 0;\n const canGenerate = !teamRequired || !!formData.team_id;\n\n const [editingKey, setEditingKey] = useState<VirtualKey | null>(null);\n const [editForm, setEditForm] = useState<UpdateKeyRequest>({});\n const [editSubmitting, setEditSubmitting] = useState(false);\n\n const selectedModels = models.filter(m => (formData.models || []).includes(m.model_name));\n const selectedTeam = teams.find(t => t.team_id === formData.team_id) ?? null;\n\n const editSelectedModels = models.filter(m => (editForm.models || []).includes(m.model_name));\n\n const handleGenerate = async () => {\n setSubmitting(true);\n try {\n const response = await onGenerateKey(formData);\n setNewKeyValue(response.key);\n setFormData(emptyForm());\n } catch (error) {\n console.error('Failed to generate key:', error);\n } finally {\n setSubmitting(false);\n }\n };\n\n const handleCloseModal = () => {\n setGenerateModalOpen(false);\n setNewKeyValue(null);\n setFormData(emptyForm());\n };\n\n const handleOpenEdit = (k: VirtualKey) => {\n setEditingKey(k);\n setEditForm(keyToEditForm(k));\n };\n\n const handleCloseEdit = () => {\n setEditingKey(null);\n setEditForm({});\n };\n\n const handleUpdate = async () => {\n if (!editingKey) return;\n setEditSubmitting(true);\n try {\n await onUpdateKey(editingKey.key, editForm);\n handleCloseEdit();\n } catch (error) {\n console.error('Failed to update key:', error);\n } finally {\n setEditSubmitting(false);\n }\n };\n\n const copyToClipboard = (text: string) => {\n navigator.clipboard.writeText(text);\n };\n\n return (\n <>\n <Paper sx={{ mb: 2 }}>\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" p={2}>\n <Typography variant=\"h6\">Virtual Keys</Typography>\n <Button\n variant=\"contained\"\n color=\"primary\"\n startIcon={<Add />}\n onClick={() => setGenerateModalOpen(true)}\n >\n Generate New Key\n </Button>\n </Box>\n\n <TableContainer>\n <Table>\n <TableHead>\n <TableRow>\n <TableCell>Alias</TableCell>\n <TableCell>Key</TableCell>\n <TableCell>Created</TableCell>\n <TableCell>Spend</TableCell>\n <TableCell>Budget</TableCell>\n <TableCell>TPM Limit</TableCell>\n <TableCell>Models</TableCell>\n <TableCell align=\"right\">Actions</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n <TableRow>\n <TableCell colSpan={8} align=\"center\">\n <CircularProgress size={24} />\n </TableCell>\n </TableRow>\n ) : keys.length === 0 ? (\n <TableRow>\n <TableCell colSpan={8} align=\"center\">\n <Typography color=\"text.secondary\">No keys found</Typography>\n </TableCell>\n </TableRow>\n ) : (\n keys.map((key) => (\n <TableRow key={key.key}>\n <TableCell>{key.key_alias || '-'}</TableCell>\n <TableCell>\n <Box display=\"flex\" alignItems=\"center\" gap={0.5}>\n <Typography variant=\"body2\" component=\"code\" sx={{ fontFamily: 'monospace' }}>\n {showKeyValue === key.key ? key.key : maskKey(key.key)}\n </Typography>\n <IconButton\n size=\"small\"\n onClick={() => setShowKeyValue(showKeyValue === key.key ? null : key.key)}\n >\n {showKeyValue === key.key ? <VisibilityOff /> : <Visibility />}\n </IconButton>\n <IconButton size=\"small\" onClick={() => copyToClipboard(key.key)}>\n <ContentCopy fontSize=\"small\" />\n </IconButton>\n </Box>\n </TableCell>\n <TableCell>{formatDate(key.created_at)}</TableCell>\n <TableCell>${key.spend?.toFixed(4) || '0.00'}</TableCell>\n <TableCell>{key.max_budget ? `$${key.max_budget}` : '-'}</TableCell>\n <TableCell>{key.tpm_limit || '-'}</TableCell>\n <TableCell>\n <Box display=\"flex\" gap={0.5} flexWrap=\"wrap\">\n {key.models?.slice(0, 2).map((model) => (\n <Chip key={model} label={model} size=\"small\" />\n ))}\n {(key.models?.length || 0) > 2 && (\n <Chip label={`+${(key.models?.length || 0) - 2}`} size=\"small\" variant=\"outlined\" />\n )}\n </Box>\n </TableCell>\n <TableCell align=\"right\">\n <IconButton onClick={() => handleOpenEdit(key)}>\n <Edit fontSize=\"small\" />\n </IconButton>\n <IconButton color=\"error\" onClick={() => onDeleteKey(key.key)}>\n <Delete />\n </IconButton>\n </TableCell>\n </TableRow>\n ))\n )}\n </TableBody>\n </Table>\n </TableContainer>\n </Paper>\n\n <Dialog open={generateModalOpen} onClose={handleCloseModal} maxWidth=\"sm\" fullWidth>\n <DialogTitle>{newKeyValue ? 'Key Generated' : 'Generate New Key'}</DialogTitle>\n <DialogContent>\n {newKeyValue ? (\n <Box>\n <Typography variant=\"body2\" color=\"text.secondary\" gutterBottom>\n Copy this key now. You won't be able to see it again.\n </Typography>\n <Box\n display=\"flex\"\n alignItems=\"center\"\n gap={1}\n mt={2}\n p={2}\n sx={{\n backgroundColor: 'grey.100',\n borderRadius: 1,\n }}\n >\n <Typography\n component=\"code\"\n color=\"text.primary\"\n sx={{ fontFamily: 'monospace', wordBreak: 'break-all', flex: 1 }}\n >\n {newKeyValue}\n </Typography>\n <IconButton onClick={() => copyToClipboard(newKeyValue)}>\n <ContentCopy />\n </IconButton>\n </Box>\n </Box>\n ) : (\n <Box display=\"flex\" flexDirection=\"column\" gap={2} mt={1}>\n <TextField\n label=\"Alias\"\n value={formData.alias || ''}\n onChange={(e) => setFormData({ ...formData, alias: e.target.value })}\n fullWidth\n />\n <TextField\n select\n label=\"Duration\"\n value={formData.duration || '30d'}\n onChange={(e) => setFormData({ ...formData, duration: e.target.value })}\n fullWidth\n >\n <MenuItem value=\"1d\">1 Day</MenuItem>\n <MenuItem value=\"7d\">7 Days</MenuItem>\n <MenuItem value=\"30d\">30 Days</MenuItem>\n <MenuItem value=\"90d\">90 Days</MenuItem>\n <MenuItem value=\"1y\">1 Year</MenuItem>\n </TextField>\n\n {teams.length > 0 && (\n <Autocomplete\n options={teams}\n getOptionLabel={t => t.team_alias || t.team_id}\n value={selectedTeam}\n onChange={(_e, team) =>\n setFormData({ ...formData, team_id: team?.team_id })\n }\n renderInput={params => (\n <TextField\n {...params}\n label=\"Team\"\n required\n error={teamRequired && !formData.team_id}\n helperText={\n teamRequired && !formData.team_id\n ? 'Pick a team to scope this key'\n : undefined\n }\n fullWidth\n />\n )}\n />\n )}\n\n {models.length > 0 && (\n <Autocomplete\n multiple\n options={models}\n groupBy={m => m.mode || 'other'}\n getOptionLabel={m => m.model_name}\n value={selectedModels}\n onChange={(_e, selected) =>\n setFormData({ ...formData, models: selected.map(m => m.model_name) })\n }\n renderOption={(props, m) => (\n <li {...props}>\n {m.model_name}\n {m.supports_function_calling && ' \uD83D\uDD27'}\n {m.supports_vision && ' \uD83D\uDC41\uFE0F'}\n </li>\n )}\n renderInput={params => (\n <TextField {...params} label=\"Models\" fullWidth />\n )}\n />\n )}\n\n <TextField\n label=\"Max Budget (USD)\"\n type=\"number\"\n value={formData.max_budget ?? ''}\n onChange={(e) =>\n setFormData({ ...formData, max_budget: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n <TextField\n label=\"TPM Limit\"\n type=\"number\"\n value={formData.tpm_limit ?? ''}\n onChange={(e) =>\n setFormData({ ...formData, tpm_limit: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n </Box>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleCloseModal}>{newKeyValue ? 'Done' : 'Cancel'}</Button>\n {!newKeyValue && (\n <Button\n onClick={handleGenerate}\n variant=\"contained\"\n color=\"primary\"\n disabled={submitting || !canGenerate}\n >\n {submitting ? <CircularProgress size={24} /> : 'Generate'}\n </Button>\n )}\n </DialogActions>\n </Dialog>\n\n <Dialog open={!!editingKey} onClose={handleCloseEdit} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Edit Key</DialogTitle>\n <DialogContent>\n {editingKey && (\n <Box display=\"flex\" flexDirection=\"column\" gap={2} mt={1}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n <code style={{ fontFamily: 'monospace' }}>{maskKey(editingKey.key)}</code>\n </Typography>\n <TextField\n label=\"Alias\"\n value={editForm.key_alias || ''}\n onChange={(e) => setEditForm({ ...editForm, key_alias: e.target.value })}\n fullWidth\n />\n\n {models.length > 0 && (\n <Autocomplete\n multiple\n options={models}\n groupBy={m => m.mode || 'other'}\n getOptionLabel={m => m.model_name}\n value={editSelectedModels}\n onChange={(_e, selected) =>\n setEditForm({ ...editForm, models: selected.map(m => m.model_name) })\n }\n renderInput={params => (\n <TextField {...params} label=\"Models\" fullWidth />\n )}\n />\n )}\n\n <TextField\n label=\"Max Budget (USD)\"\n type=\"number\"\n value={editForm.max_budget ?? ''}\n onChange={(e) =>\n setEditForm({ ...editForm, max_budget: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n <TextField\n label=\"TPM Limit\"\n type=\"number\"\n value={editForm.tpm_limit ?? ''}\n onChange={(e) =>\n setEditForm({ ...editForm, tpm_limit: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n <TextField\n label=\"RPM Limit\"\n type=\"number\"\n value={editForm.rpm_limit ?? ''}\n onChange={(e) =>\n setEditForm({ ...editForm, rpm_limit: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n </Box>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleCloseEdit}>Cancel</Button>\n <Button onClick={handleUpdate} variant=\"contained\" color=\"primary\" disabled={editSubmitting}>\n {editSubmitting ? <CircularProgress size={24} /> : 'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n </>\n );\n};\n", "import React, { useMemo, useState } from 'react';\nimport {\n Paper,\n Box,\n Typography,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n Grid,\n CircularProgress,\n Tabs,\n Tab,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Chip,\n LinearProgress,\n} from '@mui/material';\nimport {\n AreaChart,\n Area,\n BarChart,\n Bar,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n Legend,\n} from 'recharts';\nimport {\n DateRange,\n UsageMetrics,\n ModelInfo,\n UsageModelBreakdown,\n UsageKeyBreakdown,\n} from '../types';\n\ninterface UsageStatsProps {\n usage: UsageMetrics | null;\n models: ModelInfo[];\n dateRange: DateRange;\n onDateRangeChange: (range: DateRange) => void;\n loading: boolean;\n}\n\ntype DatePreset = 'today' | '7d' | '30d';\ntype TabKey = 'costs' | 'models' | 'keys';\n\nconst fmtUsd = (n: number) => `$${(n ?? 0).toFixed(n < 1 ? 4 : 2)}`;\nconst fmtInt = (n: number) => (n ?? 0).toLocaleString();\nconst fmtPct = (n: number) => `${(n * 100).toFixed(1)}%`;\n\nconst KpiCard: React.FC<{ label: string; value: string; hint?: string }> = ({ label, value, hint }) => (\n <Paper variant=\"outlined\" sx={{ p: 2, height: '100%' }}>\n <Typography variant=\"caption\" color=\"text.secondary\">{label}</Typography>\n <Typography variant=\"h5\" sx={{ mt: 0.5 }}>{value}</Typography>\n {hint ? <Typography variant=\"caption\" color=\"text.secondary\">{hint}</Typography> : null}\n </Paper>\n);\n\nexport const UsageStats: React.FC<UsageStatsProps> = ({\n usage,\n models,\n dateRange,\n onDateRangeChange,\n loading,\n}) => {\n const [selectedPreset, setSelectedPreset] = useState<DatePreset>('7d');\n const [selectedModel, setSelectedModel] = useState<string>('all');\n const [tab, setTab] = useState<TabKey>('costs');\n\n const handlePresetChange = (preset: DatePreset) => {\n setSelectedPreset(preset);\n const end = new Date();\n const start = new Date();\n if (preset === 'today') start.setHours(0, 0, 0, 0);\n else if (preset === '7d') start.setDate(start.getDate() - 7);\n else if (preset === '30d') start.setDate(start.getDate() - 30);\n onDateRangeChange({ start, end });\n };\n\n const todayRows = useMemo(() => {\n const rows = usage?.daily_by_model ?? [];\n if (rows.length === 0) return [];\n // Pick the most recent date present in the data \u2014 that's the latest\n // \"current day\" the proxy has aggregated, even if today has no traffic yet.\n const latestDate = rows.map(r => r.date).sort().slice(-1)[0];\n return rows\n .filter(r => r.date === latestDate)\n .map(r => ({\n model: r.model,\n promptTokens: r.prompt_tokens,\n completionTokens: r.completion_tokens,\n }))\n .filter(r => r.promptTokens + r.completionTokens > 0)\n .sort((a, b) => (b.promptTokens + b.completionTokens) - (a.promptTokens + a.completionTokens));\n }, [usage]);\n\n const todayLabel = useMemo(() => {\n const rows = usage?.daily_by_model ?? [];\n if (rows.length === 0) return null;\n return rows.map(r => r.date).sort().slice(-1)[0];\n }, [usage]);\n\n const dailyData = useMemo(\n () =>\n (usage?.daily_usage ?? []).map(d => ({\n date: d.date,\n spend: d.spend,\n promptTokens: d.prompt_tokens,\n completionTokens: d.completion_tokens,\n totalTokens: d.total_tokens,\n apiRequests: d.api_requests,\n successfulRequests: d.successful_requests,\n failedRequests: d.failed_requests,\n })),\n [usage],\n );\n\n const modelRows = useMemo(() => {\n const entries = Object.entries<UsageModelBreakdown>(usage?.usage_by_model ?? {}).map(([model, d]) => ({\n model,\n spend: d.total_spend,\n promptTokens: d.prompt_tokens,\n completionTokens: d.completion_tokens,\n totalTokens: d.total_tokens,\n apiRequests: d.api_requests,\n successfulRequests: d.successful_requests,\n failedRequests: d.failed_requests,\n successRate: d.api_requests > 0 ? d.successful_requests / d.api_requests : 0,\n }));\n return selectedModel === 'all' ? entries : entries.filter(e => e.model === selectedModel);\n }, [usage, selectedModel]);\n\n const keyRows = useMemo(\n () =>\n Object.entries<UsageKeyBreakdown>(usage?.usage_by_key ?? {}).map(([keyHash, d]) => ({\n keyHash,\n keyAlias: d.key_alias ?? keyHash.slice(0, 8),\n teamId: d.team_id ?? null,\n models: d.models,\n spend: d.total_spend,\n totalTokens: d.total_tokens,\n promptTokens: d.prompt_tokens,\n completionTokens: d.completion_tokens,\n apiRequests: d.api_requests,\n successfulRequests: d.successful_requests,\n failedRequests: d.failed_requests,\n successRate: d.api_requests > 0 ? d.successful_requests / d.api_requests : 0,\n })),\n [usage],\n );\n\n const totalRequests = usage?.api_requests ?? 0;\n const overallSuccessRate = totalRequests > 0 ? (usage?.successful_requests ?? 0) / totalRequests : 0;\n\n if (loading) {\n return (\n <Paper sx={{ p: 2 }}>\n <Box display=\"flex\" justifyContent=\"center\" p={4}>\n <CircularProgress />\n </Box>\n </Paper>\n );\n }\n\n return (\n <Paper sx={{ p: 2 }}>\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={2} flexWrap=\"wrap\" gap={2}>\n <Typography variant=\"h6\">Usage Analytics</Typography>\n <Box display=\"flex\" gap={2} alignItems=\"center\" flexWrap=\"wrap\">\n <FormControl size=\"small\" sx={{ minWidth: 140 }}>\n <InputLabel>Period</InputLabel>\n <Select\n value={selectedPreset}\n label=\"Period\"\n onChange={e => handlePresetChange(e.target.value as DatePreset)}\n >\n <MenuItem value=\"today\">Today</MenuItem>\n <MenuItem value=\"7d\">Last 7 days</MenuItem>\n <MenuItem value=\"30d\">Last 30 days</MenuItem>\n </Select>\n </FormControl>\n {tab === 'models' && (\n <FormControl size=\"small\" sx={{ minWidth: 180 }}>\n <InputLabel>Model</InputLabel>\n <Select\n value={selectedModel}\n label=\"Model\"\n onChange={e => setSelectedModel(e.target.value)}\n >\n <MenuItem value=\"all\">All Models</MenuItem>\n {models.map(m => (\n <MenuItem key={m.model_name} value={m.model_name}>\n {m.model_name}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n )}\n </Box>\n </Box>\n\n <Grid container spacing={2} sx={{ mb: 2 }}>\n <Grid item xs={6} sm={3}>\n <KpiCard label=\"Total Spend\" value={fmtUsd(usage?.total_spend ?? 0)} />\n </Grid>\n <Grid item xs={6} sm={3}>\n <KpiCard label=\"Total Requests\" value={fmtInt(totalRequests)} hint={`${fmtInt(usage?.failed_requests ?? 0)} failed`} />\n </Grid>\n <Grid item xs={6} sm={3}>\n <KpiCard label=\"Success Rate\" value={totalRequests > 0 ? fmtPct(overallSuccessRate) : '\u2014'} />\n </Grid>\n <Grid item xs={6} sm={3}>\n <KpiCard\n label=\"Total Tokens\"\n value={fmtInt(usage?.total_tokens ?? 0)}\n hint={`${fmtInt(usage?.prompt_tokens ?? 0)} in \u00B7 ${fmtInt(usage?.completion_tokens ?? 0)} out`}\n />\n </Grid>\n </Grid>\n\n <Tabs value={tab} onChange={(_, v) => setTab(v as TabKey)} sx={{ mb: 2 }}>\n <Tab value=\"costs\" label=\"Costs\" />\n <Tab value=\"models\" label=\"Model Activity\" />\n <Tab value=\"keys\" label=\"Key Activity\" />\n </Tabs>\n\n {tab === 'costs' && (\n <Grid container spacing={3}>\n <Grid item xs={12} md={6}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Daily Spend\n </Typography>\n <Box height={260}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={dailyData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"date\" tick={{ fontSize: 12 }} />\n <YAxis tick={{ fontSize: 12 }} tickFormatter={v => `$${v.toFixed(2)}`} />\n <Tooltip formatter={(value: number) => [`$${value.toFixed(4)}`, 'Spend']} />\n <Area type=\"monotone\" dataKey=\"spend\" stroke=\"#8884d8\" fill=\"#8884d8\" fillOpacity={0.3} />\n </AreaChart>\n </ResponsiveContainer>\n </Box>\n </Grid>\n <Grid item xs={12} md={6}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Daily Requests\n </Typography>\n <Box height={260}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={dailyData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"date\" tick={{ fontSize: 12 }} />\n <YAxis tick={{ fontSize: 12 }} />\n <Tooltip />\n <Legend />\n <Bar dataKey=\"successfulRequests\" name=\"Successful\" fill=\"#82ca9d\" stackId=\"r\" />\n <Bar dataKey=\"failedRequests\" name=\"Failed\" fill=\"#e57373\" stackId=\"r\" />\n </BarChart>\n </ResponsiveContainer>\n </Box>\n </Grid>\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n {todayLabel ? `Tokens In / Out by Model \u2014 ${todayLabel}` : 'Tokens In / Out by Model \u2014 Today'}\n </Typography>\n <Box height={300}>\n {todayRows.length === 0 ? (\n <Box display=\"flex\" alignItems=\"center\" justifyContent=\"center\" height=\"100%\">\n <Typography color=\"text.secondary\">No token activity for the latest day</Typography>\n </Box>\n ) : (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={todayRows} layout=\"vertical\" margin={{ left: 60 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis type=\"number\" tick={{ fontSize: 12 }} tickFormatter={fmtInt} />\n <YAxis type=\"category\" dataKey=\"model\" tick={{ fontSize: 11 }} width={180} />\n <Tooltip formatter={(value: number) => fmtInt(value)} />\n <Legend />\n <Bar dataKey=\"promptTokens\" name=\"Input (prompt)\" fill=\"#8884d8\" stackId=\"io\" />\n <Bar dataKey=\"completionTokens\" name=\"Output (completion)\" fill=\"#82ca9d\" stackId=\"io\" />\n </BarChart>\n </ResponsiveContainer>\n )}\n </Box>\n </Grid>\n </Grid>\n )}\n\n {tab === 'models' && (\n <Grid container spacing={3}>\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Tokens by Model\n </Typography>\n <Box height={260}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={modelRows}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"model\" tick={{ fontSize: 10 }} interval={0} angle={-15} textAnchor=\"end\" height={60} />\n <YAxis tick={{ fontSize: 12 }} />\n <Tooltip />\n <Legend />\n <Bar dataKey=\"promptTokens\" name=\"Prompt\" fill=\"#8884d8\" stackId=\"t\" />\n <Bar dataKey=\"completionTokens\" name=\"Completion\" fill=\"#82ca9d\" stackId=\"t\" />\n </BarChart>\n </ResponsiveContainer>\n </Box>\n </Grid>\n <Grid item xs={12}>\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Model</TableCell>\n <TableCell align=\"right\">Spend</TableCell>\n <TableCell align=\"right\">Requests</TableCell>\n <TableCell align=\"right\">Success</TableCell>\n <TableCell align=\"right\">Failed</TableCell>\n <TableCell align=\"right\">Prompt</TableCell>\n <TableCell align=\"right\">Completion</TableCell>\n <TableCell sx={{ minWidth: 120 }}>Success rate</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {modelRows.length === 0 ? (\n <TableRow><TableCell colSpan={8} align=\"center\">No model activity</TableCell></TableRow>\n ) : modelRows\n .sort((a, b) => b.spend - a.spend || b.totalTokens - a.totalTokens)\n .map(r => (\n <TableRow key={r.model}>\n <TableCell>{r.model}</TableCell>\n <TableCell align=\"right\">{fmtUsd(r.spend)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.apiRequests)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.successfulRequests)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.failedRequests)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.promptTokens)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.completionTokens)}</TableCell>\n <TableCell>\n {r.apiRequests > 0 ? (\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <LinearProgress\n variant=\"determinate\"\n value={r.successRate * 100}\n sx={{ flex: 1, height: 6, borderRadius: 3 }}\n />\n <Typography variant=\"caption\">{fmtPct(r.successRate)}</Typography>\n </Box>\n ) : '\u2014'}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n </Grid>\n </Grid>\n )}\n\n {tab === 'keys' && (\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Key</TableCell>\n <TableCell>Models</TableCell>\n <TableCell align=\"right\">Spend</TableCell>\n <TableCell align=\"right\">Requests</TableCell>\n <TableCell align=\"right\">Tokens</TableCell>\n <TableCell align=\"right\">Failed</TableCell>\n <TableCell sx={{ minWidth: 120 }}>Success rate</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {keyRows.length === 0 ? (\n <TableRow><TableCell colSpan={7} align=\"center\">No key activity</TableCell></TableRow>\n ) : keyRows\n .sort((a, b) => b.spend - a.spend || b.apiRequests - a.apiRequests)\n .map(r => (\n <TableRow key={r.keyHash}>\n <TableCell>\n <Typography variant=\"body2\">{r.keyAlias}</Typography>\n {r.teamId ? (\n <Typography variant=\"caption\" color=\"text.secondary\">team: {r.teamId}</Typography>\n ) : null}\n </TableCell>\n <TableCell>\n <Box display=\"flex\" gap={0.5} flexWrap=\"wrap\">\n {r.models.map(m => (\n <Chip key={m} label={m} size=\"small\" variant=\"outlined\" />\n ))}\n </Box>\n </TableCell>\n <TableCell align=\"right\">{fmtUsd(r.spend)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.apiRequests)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.totalTokens)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.failedRequests)}</TableCell>\n <TableCell>\n {r.apiRequests > 0 ? (\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <LinearProgress\n variant=\"determinate\"\n value={r.successRate * 100}\n sx={{ flex: 1, height: 6, borderRadius: 3 }}\n />\n <Typography variant=\"caption\">{fmtPct(r.successRate)}</Typography>\n </Box>\n ) : '\u2014'}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n )}\n </Paper>\n );\n};\n", "import React, { useState } from 'react';\nimport {\n Paper,\n Box,\n Typography,\n LinearProgress,\n Chip,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TableContainer,\n Collapse,\n IconButton,\n CircularProgress,\n} from '@mui/material';\nimport { ExpandMore, ExpandLess, Group } from '@mui/icons-material';\nimport {\n AreaChart,\n Area,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n} from 'recharts';\nimport { TeamInfo, UsageMetrics, DateRange } from '../types';\n\ninterface TeamCardProps {\n team: TeamInfo;\n usage: UsageMetrics | null;\n usageLoading: boolean;\n}\n\nconst TeamCard: React.FC<TeamCardProps> = ({ team, usage, usageLoading }) => {\n const [expanded, setExpanded] = useState(false);\n\n const budget = team.max_budget ?? 0;\n const spend = team.spend ?? 0;\n const budgetPct = budget > 0 ? Math.min((spend / budget) * 100, 100) : 0;\n const isOver = budget > 0 && spend >= budget;\n const isNear = budget > 0 && spend >= budget * 0.8 && !isOver;\n\n const dailyData = usage?.daily_usage?.map(d => ({ date: d.date, spend: d.spend })) ?? [];\n\n return (\n <Paper variant=\"outlined\" sx={{ p: 2, mb: 2 }}>\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <Group color=\"action\" />\n <Box flexGrow={1}>\n <Typography variant=\"subtitle1\" fontWeight={600}>\n {team.team_alias ?? team.team_id}\n </Typography>\n {team.models?.length ? (\n <Box display=\"flex\" gap={0.5} flexWrap=\"wrap\" mt={0.5}>\n {team.models.map(m => (\n <Chip key={m} label={m} size=\"small\" variant=\"outlined\" />\n ))}\n </Box>\n ) : (\n <Typography variant=\"caption\" color=\"text.secondary\">All models</Typography>\n )}\n </Box>\n <IconButton size=\"small\" onClick={() => setExpanded(e => !e)}>\n {expanded ? <ExpandLess /> : <ExpandMore />}\n </IconButton>\n </Box>\n\n {budget > 0 && (\n <Box mt={1.5}>\n <Box display=\"flex\" justifyContent=\"space-between\" mb={0.5}>\n <Typography variant=\"body2\">\n ${spend.toFixed(2)} / ${budget.toFixed(2)}\n </Typography>\n {isOver && <Chip label=\"Over Budget\" size=\"small\" color=\"error\" />}\n {isNear && <Chip label=\"Near Limit\" size=\"small\" color=\"warning\" />}\n </Box>\n <LinearProgress\n variant=\"determinate\"\n value={budgetPct}\n color={isOver ? 'error' : isNear ? 'warning' : 'primary'}\n sx={{ height: 6, borderRadius: 1 }}\n />\n </Box>\n )}\n\n <Collapse in={expanded}>\n <Box mt={2}>\n {usageLoading ? (\n <Box display=\"flex\" justifyContent=\"center\" p={2}>\n <CircularProgress size={24} />\n </Box>\n ) : dailyData.length > 0 ? (\n <>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Daily Spend\n </Typography>\n <Box height={160}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={dailyData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"date\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} tickFormatter={v => `$${v.toFixed(2)}`} />\n <Tooltip formatter={(v: number) => [`$${v.toFixed(4)}`, 'Spend']} />\n <Area type=\"monotone\" dataKey=\"spend\" stroke=\"#8884d8\" fill=\"#8884d8\" fillOpacity={0.3} />\n </AreaChart>\n </ResponsiveContainer>\n </Box>\n </>\n ) : null}\n\n {team.members_with_roles?.length ? (\n <Box mt={2}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Members\n </Typography>\n <TableContainer>\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>User</TableCell>\n <TableCell>Role</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {team.members_with_roles.map(m => (\n <TableRow key={m.user_id}>\n <TableCell sx={{ fontFamily: 'monospace', fontSize: 12 }}>{m.user_id}</TableCell>\n <TableCell>\n <Chip\n label={m.role}\n size=\"small\"\n color={m.role === 'admin' ? 'primary' : 'default'}\n />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n </Box>\n ) : null}\n </Box>\n </Collapse>\n </Paper>\n );\n};\n\ninterface TeamUsageProps {\n teams: TeamInfo[];\n loading: boolean;\n dateRange: DateRange;\n getTeamUsage: (teamId: string) => UsageMetrics | null;\n getTeamUsageLoading: (teamId: string) => boolean;\n}\n\nexport const TeamUsage: React.FC<TeamUsageProps> = ({\n teams,\n loading,\n getTeamUsage,\n getTeamUsageLoading,\n}) => {\n if (loading) {\n return (\n <Paper sx={{ p: 2 }}>\n <LinearProgress />\n </Paper>\n );\n }\n\n if (!teams.length) {\n return (\n <Paper sx={{ p: 2 }}>\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <Group color=\"disabled\" />\n <Typography color=\"text.secondary\" variant=\"body2\">\n No team membership found in LiteLLM for this account.\n </Typography>\n </Box>\n </Paper>\n );\n }\n\n return (\n <Box>\n <Typography variant=\"h6\" mb={1}>Teams</Typography>\n {teams.map(team => (\n <TeamCard\n key={team.team_id}\n team={team}\n usage={getTeamUsage(team.team_id)}\n usageLoading={getTeamUsageLoading(team.team_id)}\n />\n ))}\n </Box>\n );\n};\n", "import React, { useState, useCallback, useMemo } from 'react';\nimport { Grid, Box, Snackbar, Alert, CircularProgress, Typography, Paper } from '@mui/material';\nimport { useAsync, useAsyncRetry } from 'react-use';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { DashboardHeader } from './DashboardHeader';\nimport { KeysTable } from './KeysTable';\nimport { UsageStats } from './UsageStats';\nimport { TeamUsage } from './TeamUsage';\nimport { liteLlmApiRef } from '../api';\nimport { DateRange, GenerateKeyRequest, GenerateKeyResponse, UpdateKeyRequest, UsageMetrics } from '../types';\n\nexport const LiteLLMPage: React.FC = () => {\n const api = useApi(liteLlmApiRef);\n\n const [dateRange, setDateRange] = useState<DateRange>(() => {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n return { start, end };\n });\n\n const [snackbar, setSnackbar] = useState<{ message: string; severity: 'success' | 'error' } | null>(null);\n\n // Team usage cache: teamId -> UsageMetrics\n const [teamUsageCache, setTeamUsageCache] = useState<Record<string, UsageMetrics | null>>({});\n const [teamUsageLoading, setTeamUsageLoading] = useState<Record<string, boolean>>({});\n\n const { value: userInfo, loading: userLoading, error: userError } = useAsync(\n () => api.getUserInfo(),\n [api],\n );\n\n const { value: keys, loading: keysLoading, retry: refreshKeys } = useAsyncRetry(\n async () => {\n try {\n return await api.listKeys();\n } catch (e: any) {\n setSnackbar({ message: `Failed to load keys: ${e.message}`, severity: 'error' });\n return [];\n }\n },\n [api],\n );\n\n const { value: allModels, loading: modelsLoading } = useAsync(\n () => api.listModels().catch(() => []),\n [api],\n );\n\n const { value: allTeams, loading: teamsLoading } = useAsync(\n () => api.getTeams().catch(() => []),\n [api],\n );\n\n // Filter to teams the current user belongs to\n const teams = useMemo(() => {\n if (!allTeams?.length) return [];\n if (!userInfo) return allTeams;\n const userId = userInfo.user_id;\n if (userInfo.teams?.length) {\n return allTeams.filter(t => userInfo.teams!.includes(t.team_id));\n }\n const byMembership = allTeams.filter(t =>\n t.members_with_roles?.some(m => m.user_id === userId),\n );\n return byMembership.length > 0 ? byMembership : allTeams;\n }, [allTeams, userInfo]);\n\n const { value: usage, loading: usageLoading } = useAsync(async () => {\n const startDate = dateRange.start.toISOString().split('T')[0];\n const endDate = dateRange.end.toISOString().split('T')[0];\n return api.getUsage(startDate, endDate);\n }, [api, dateRange]);\n\n // Fetch team usage on demand when a team card is expanded\n const loadTeamUsage = useCallback(async (teamId: string) => {\n if (teamUsageCache[teamId] !== undefined || teamUsageLoading[teamId]) return;\n setTeamUsageLoading(prev => ({ ...prev, [teamId]: true }));\n try {\n const startDate = dateRange.start.toISOString().split('T')[0];\n const endDate = dateRange.end.toISOString().split('T')[0];\n const data = await api.getTeamUsage(teamId, startDate, endDate);\n setTeamUsageCache(prev => ({ ...prev, [teamId]: data }));\n } catch {\n setTeamUsageCache(prev => ({ ...prev, [teamId]: null }));\n } finally {\n setTeamUsageLoading(prev => ({ ...prev, [teamId]: false }));\n }\n }, [api, dateRange, teamUsageCache, teamUsageLoading]);\n\n // Models available for key generation: intersection of all models with user-level\n // and team-level restrictions. If a user has no model restrictions, all models are allowed.\n const allowedModels = useMemo(() => {\n if (!allModels?.length) return [];\n const userModels = userInfo?.models;\n const teamModels = teams?.flatMap(t => t.models ?? []);\n const hasUserRestriction = userModels && userModels.length > 0;\n const hasTeamRestriction = teamModels && teamModels.length > 0;\n if (!hasUserRestriction && !hasTeamRestriction) return allModels;\n const allowed = new Set([\n ...(hasUserRestriction ? userModels! : allModels.map(m => m.model_name)),\n ...(hasTeamRestriction ? teamModels! : []),\n ]);\n return allModels.filter(m => allowed.has(m.model_name));\n }, [allModels, userInfo, teams]);\n\n const handleGenerateKey = useCallback(\n async (request: GenerateKeyRequest): Promise<GenerateKeyResponse> => {\n const response = await api.generateKey(request);\n setSnackbar({ message: 'Key generated successfully', severity: 'success' });\n refreshKeys();\n return response;\n },\n [api, refreshKeys],\n );\n\n const handleUpdateKey = useCallback(\n async (keyId: string, request: UpdateKeyRequest) => {\n try {\n await api.updateKey(keyId, request);\n setSnackbar({ message: 'Key updated successfully', severity: 'success' });\n refreshKeys();\n } catch (e: any) {\n setSnackbar({ message: `Failed to update key: ${e.message}`, severity: 'error' });\n throw e;\n }\n },\n [api, refreshKeys],\n );\n\n const handleDeleteKey = useCallback(\n async (keyId: string) => {\n try {\n await api.deleteKey(keyId);\n setSnackbar({ message: 'Key revoked successfully', severity: 'success' });\n refreshKeys();\n } catch (e: any) {\n setSnackbar({ message: `Failed to revoke key: ${e.message}`, severity: 'error' });\n }\n },\n [api, refreshKeys],\n );\n\n const isInitialLoading = userLoading && !userInfo;\n\n if (isInitialLoading) {\n return (\n <Box display=\"flex\" justifyContent=\"center\" alignItems=\"center\" minHeight=\"50vh\">\n <CircularProgress />\n </Box>\n );\n }\n\n // User exists in Backstage but has no LiteLLM account\n if (userError || !userInfo) {\n const isProvisioningEnabled = (userError as any)?.body?.provisioning === true;\n const hint = (userError as any)?.body?.hint;\n return (\n <Box p={3}>\n <Paper sx={{ p: 3 }}>\n <Typography variant=\"h6\" gutterBottom>Account not provisioned</Typography>\n <Typography color=\"text.secondary\" paragraph>\n Your Backstage account is not linked to a LiteLLM user.\n </Typography>\n {hint ? (\n <Typography variant=\"body2\" color=\"text.secondary\">{hint}</Typography>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {isProvisioningEnabled\n ? 'Auto-provisioning is enabled but failed. Check the backend logs.'\n : 'Set litellm.provisioning.enabled: true in app-config.yaml to enable auto-provisioning, or ask your administrator to create the account manually.'}\n </Typography>\n )}\n </Paper>\n </Box>\n );\n }\n\n return (\n <Box p={3}>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <DashboardHeader userInfo={userInfo} teams={teams ?? []} loading={userLoading || teamsLoading} />\n </Grid>\n\n <Grid item xs={12}>\n <TeamUsage\n teams={teams ?? []}\n loading={teamsLoading}\n dateRange={dateRange}\n getTeamUsage={teamId => {\n if (teamUsageCache[teamId] === undefined) loadTeamUsage(teamId);\n return teamUsageCache[teamId] ?? null;\n }}\n getTeamUsageLoading={teamId => teamUsageLoading[teamId] ?? false}\n />\n </Grid>\n\n <Grid item xs={12}>\n <KeysTable\n keys={keys ?? []}\n models={allowedModels}\n teams={teams ?? []}\n loading={keysLoading || modelsLoading}\n onGenerateKey={handleGenerateKey}\n onUpdateKey={handleUpdateKey}\n onDeleteKey={handleDeleteKey}\n />\n </Grid>\n\n <Grid item xs={12}>\n <UsageStats\n usage={usage ?? null}\n models={allModels ?? []}\n dateRange={dateRange}\n onDateRangeChange={setDateRange}\n loading={usageLoading}\n />\n </Grid>\n </Grid>\n\n <Snackbar\n open={!!snackbar}\n autoHideDuration={5000}\n onClose={() => setSnackbar(null)}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n >\n {snackbar ? (\n <Alert severity={snackbar.severity} onClose={() => setSnackbar(null)}>\n {snackbar.message}\n </Alert>\n ) : undefined}\n </Snackbar>\n </Box>\n );\n};\n", "import React from 'react';\nimport { TrendingUp as TrendingUpIcon } from '@mui/icons-material';\nimport {\n createFrontendPlugin,\n createApiExtension,\n createPageExtension,\n createApiFactory,\n createSidebarExtension,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { liteLlmApiRef, LiteLlmApi } from './api';\n\nexport const litellmPlugin = createFrontendPlugin({\n id: 'litellm',\n extensions: [\n createApiExtension({\n factory: createApiFactory({\n api: liteLlmApiRef,\n deps: { fetchApi: fetchApiRef },\n factory: ({ fetchApi }) => new LiteLlmApi(fetchApi),\n }),\n }),\n createSidebarExtension({\n id: 'root',\n title: 'LiteLLM',\n icon: <TrendingUpIcon />,\n defaultPath: '/litellm',\n }),\n createPageExtension({\n defaultPath: '/litellm',\n loader: async () => {\n const { LiteLLMPage } = await import('./components/LiteLLMPage');\n return React.createElement(LiteLLMPage);\n },\n }),\n ],\n});\n", "export { litellmPlugin } from './plugin';\nexport { LiteLLMPage } from './components/LiteLLMPage';\nexport { DashboardHeader } from './components/DashboardHeader';\nexport { KeysTable } from './components/KeysTable';\nexport { UsageStats } from './components/UsageStats';\nexport { TeamUsage } from './components/TeamUsage';\nexport { LiteLlmApi, liteLlmApiRef } from './api';\nexport type { LiteLlmApiInterface } from './api';\nexport * from './types';\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/api.ts", "../src/components/DashboardHeader.tsx", "../src/components/KeysTable.tsx", "../src/components/UsageStats.tsx", "../src/components/TeamUsage.tsx", "../src/components/LiteLLMPage.tsx", "../src/plugin.tsx", "../src/index.ts"],
4
+ "sourcesContent": ["import { createApiRef, FetchApi } from '@backstage/core-plugin-api';\nimport {\n UserInfo,\n VirtualKey,\n ModelInfo,\n UsageMetrics,\n TeamInfo,\n GenerateKeyRequest,\n GenerateKeyResponse,\n UpdateKeyRequest,\n} from './types';\n\nclass ApiError extends Error {\n body: unknown;\n status: number;\n constructor(message: string, status: number, body: unknown) {\n super(message);\n this.status = status;\n this.body = body;\n }\n}\n\nexport interface LiteLlmApiInterface {\n getUserInfo(): Promise<UserInfo>;\n listKeys(): Promise<VirtualKey[]>;\n generateKey(request: GenerateKeyRequest): Promise<GenerateKeyResponse>;\n updateKey(keyId: string, request: UpdateKeyRequest): Promise<VirtualKey>;\n deleteKey(keyId: string): Promise<{ success: boolean }>;\n listModels(): Promise<ModelInfo[]>;\n getTeams(): Promise<TeamInfo[]>;\n getUsage(startDate: string, endDate: string): Promise<UsageMetrics>;\n getTeamUsage(teamId: string, startDate: string, endDate: string): Promise<UsageMetrics>;\n}\n\nexport const liteLlmApiRef = createApiRef<LiteLlmApiInterface>({\n id: 'plugin.litellm.api',\n});\n\nexport class LiteLlmApi implements LiteLlmApiInterface {\n private fetchApi: FetchApi;\n private basePath: string;\n\n constructor(fetchApi: FetchApi, basePath: string = '/api/litellm') {\n this.fetchApi = fetchApi;\n this.basePath = basePath;\n }\n\n private async throwIfNotOk(response: Response): Promise<void> {\n if (!response.ok) {\n let body: unknown;\n try { body = await response.json(); } catch { body = await response.text().catch(() => ''); }\n throw new ApiError(`${response.status} ${response.statusText}`, response.status, body);\n }\n }\n\n private async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${this.basePath}${path}`, window.location.origin);\n if (params) {\n Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value));\n }\n const response = await this.fetchApi.fetch(url.toString());\n await this.throwIfNotOk(response);\n return response.json();\n }\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n const response = await this.fetchApi.fetch(`${this.basePath}${path}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n await this.throwIfNotOk(response);\n return response.json();\n }\n\n private async del<T>(path: string): Promise<T> {\n const response = await this.fetchApi.fetch(`${this.basePath}${path}`, {\n method: 'DELETE',\n headers: { 'Content-Type': 'application/json' },\n });\n await this.throwIfNotOk(response);\n return response.json();\n }\n\n // User identity is resolved server-side from the Backstage Bearer token.\n // No user_id param needed on the frontend.\n async getUserInfo(): Promise<UserInfo> {\n return this.get<UserInfo>('/user/info');\n }\n\n async listKeys(): Promise<VirtualKey[]> {\n return this.get<VirtualKey[]>('/keys');\n }\n\n async generateKey(request: GenerateKeyRequest): Promise<GenerateKeyResponse> {\n return this.post<GenerateKeyResponse>('/keys/generate', request);\n }\n\n async updateKey(keyId: string, request: UpdateKeyRequest): Promise<VirtualKey> {\n return this.post<VirtualKey>(`/keys/${encodeURIComponent(keyId)}/update`, request);\n }\n\n async deleteKey(keyId: string): Promise<{ success: boolean }> {\n return this.del<{ success: boolean }>(`/keys/${encodeURIComponent(keyId)}`);\n }\n\n async listModels(): Promise<ModelInfo[]> {\n return this.get<ModelInfo[]>('/models');\n }\n\n async getTeams(): Promise<TeamInfo[]> {\n return this.get<TeamInfo[]>('/teams');\n }\n\n async getUsage(startDate: string, endDate: string): Promise<UsageMetrics> {\n return this.get<UsageMetrics>('/usage', { start_date: startDate, end_date: endDate });\n }\n\n async getTeamUsage(teamId: string, startDate: string, endDate: string): Promise<UsageMetrics> {\n return this.get<UsageMetrics>(`/teams/${encodeURIComponent(teamId)}/usage`, {\n start_date: startDate,\n end_date: endDate,\n });\n }\n}\n", "import React from 'react';\nimport { Box, Typography, LinearProgress, Paper, Chip } from '@mui/material';\nimport { Warning } from '@mui/icons-material';\nimport { UserInfo, TeamInfo } from '../types';\n\ninterface DashboardHeaderProps {\n userInfo: UserInfo;\n teams: TeamInfo[];\n loading: boolean;\n}\n\nexport const DashboardHeader: React.FC<DashboardHeaderProps> = ({ userInfo, teams, loading }) => {\n if (loading) {\n return (\n <Paper sx={{ p: 2, mb: 2 }}>\n <LinearProgress />\n </Paper>\n );\n }\n\n const displayName = userInfo.user_email ?? userInfo.email ?? userInfo.user_id;\n const budget = userInfo.max_budget ?? 0;\n const spend = userInfo.spend ?? userInfo.current_spend ?? 0;\n const budgetPct = budget > 0 ? Math.min((spend / budget) * 100, 100) : 0;\n const isOver = budget > 0 && spend >= budget;\n const isNear = budget > 0 && spend >= budget * 0.8 && !isOver;\n\n return (\n <Paper sx={{ p: 2, mb: 2 }}>\n <Box display=\"flex\" alignItems=\"flex-start\" gap={2} flexWrap=\"wrap\">\n <Box flexGrow={1}>\n <Typography variant=\"h6\">{displayName}</Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {userInfo.user_id}\n </Typography>\n\n {teams.length > 0 && (\n <Box display=\"flex\" gap={0.75} flexWrap=\"wrap\" mt={1}>\n {teams.map(team => (\n <Chip\n key={team.team_id}\n label={team.team_alias || team.team_id}\n size=\"small\"\n variant=\"outlined\"\n color=\"primary\"\n />\n ))}\n </Box>\n )}\n </Box>\n\n {budget > 0 && (\n <Box minWidth={220}>\n <Box display=\"flex\" justifyContent=\"space-between\" mb={0.5}>\n <Typography variant=\"body2\">\n ${spend.toFixed(2)} / ${budget.toFixed(2)}\n </Typography>\n {isOver && <Chip icon={<Warning />} label=\"Over Budget\" size=\"small\" color=\"error\" />}\n {isNear && <Chip label=\"Near Limit\" size=\"small\" color=\"warning\" />}\n </Box>\n <LinearProgress\n variant=\"determinate\"\n value={budgetPct}\n color={isOver ? 'error' : isNear ? 'warning' : 'primary'}\n sx={{ height: 8, borderRadius: 1 }}\n />\n </Box>\n )}\n </Box>\n </Paper>\n );\n};\n", "import React, { useEffect, useState } from 'react';\nimport {\n Paper,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Button,\n IconButton,\n Box,\n Typography,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n TextField,\n MenuItem,\n Chip,\n CircularProgress,\n Autocomplete,\n} from '@mui/material';\nimport { ContentCopy, Delete, Add, Edit, Visibility, VisibilityOff } from '@mui/icons-material';\nimport {\n VirtualKey,\n ModelInfo,\n TeamInfo,\n GenerateKeyRequest,\n GenerateKeyResponse,\n UpdateKeyRequest,\n} from '../types';\n\ninterface KeysTableProps {\n keys: VirtualKey[];\n models: ModelInfo[];\n teams: TeamInfo[];\n loading: boolean;\n onGenerateKey: (request: GenerateKeyRequest) => Promise<GenerateKeyResponse>;\n onUpdateKey: (keyId: string, request: UpdateKeyRequest) => Promise<void>;\n onDeleteKey: (keyId: string) => Promise<void>;\n}\n\nconst maskKey = (key: string): string => {\n if (key.length <= 8) return '***';\n return `${key.slice(0, 4)}...${key.slice(-4)}`;\n};\n\nconst formatDate = (dateStr: string): string => {\n try {\n return new Date(dateStr).toLocaleDateString();\n } catch {\n return dateStr;\n }\n};\n\nconst emptyForm = (): GenerateKeyRequest => ({\n alias: '',\n models: [],\n duration: '30d',\n max_budget: undefined,\n tpm_limit: undefined,\n team_id: undefined,\n key_type: 'llm_api',\n});\n\nconst keyToEditForm = (k: VirtualKey): UpdateKeyRequest => ({\n key_alias: k.key_alias ?? '',\n models: k.models ?? [],\n max_budget: k.max_budget,\n tpm_limit: k.tpm_limit,\n rpm_limit: k.rpm_limit,\n});\n\nexport const KeysTable: React.FC<KeysTableProps> = ({\n keys,\n models,\n teams,\n loading,\n onGenerateKey,\n onUpdateKey,\n onDeleteKey,\n}) => {\n const [generateModalOpen, setGenerateModalOpen] = useState(false);\n const [showKeyValue, setShowKeyValue] = useState<string | null>(null);\n const [newKeyValue, setNewKeyValue] = useState<string | null>(null);\n const [formData, setFormData] = useState<GenerateKeyRequest>(emptyForm());\n const [submitting, setSubmitting] = useState(false);\n\n // Default to the user's first team when the modal opens so users in exactly\n // one team don't need to pick. Multi-team users see the picker pre-filled\n // and can change it. Teams are already filtered to the current user upstream.\n useEffect(() => {\n if (!generateModalOpen) return;\n if (!formData.team_id && teams.length > 0) {\n setFormData(f => ({ ...f, team_id: teams[0].team_id }));\n }\n }, [generateModalOpen, teams, formData.team_id]);\n\n const canGenerate = true; // Always allow generation regardless of team selection\n\n const [editingKey, setEditingKey] = useState<VirtualKey | null>(null);\n const [editForm, setEditForm] = useState<UpdateKeyRequest>({});\n const [editSubmitting, setEditSubmitting] = useState(false);\n\n const selectedModels = models.filter(m => (formData.models || []).includes(m.model_name));\n const selectedTeam = teams.find(t => t.team_id === formData.team_id) ?? null;\n\n const editSelectedModels = models.filter(m => (editForm.models || []).includes(m.model_name));\n\n const handleGenerate = async () => {\n setSubmitting(true);\n try {\n const response = await onGenerateKey(formData);\n setNewKeyValue(response.key);\n setFormData(emptyForm());\n // Close dialog after showing the generated key\n setTimeout(() => {\n setGenerateModalOpen(false);\n setNewKeyValue(null);\n }, 1500);\n } catch (error) {\n console.error('Failed to generate key:', error);\n } finally {\n setSubmitting(false);\n }\n };\n\n const handleCloseModal = () => {\n setGenerateModalOpen(false);\n setNewKeyValue(null);\n setFormData(emptyForm());\n };\n\n const handleOpenEdit = (k: VirtualKey) => {\n setEditingKey(k);\n setEditForm(keyToEditForm(k));\n };\n\n const handleCloseEdit = () => {\n setEditingKey(null);\n setEditForm({});\n };\n\n const handleUpdate = async () => {\n if (!editingKey) return;\n setEditSubmitting(true);\n try {\n await onUpdateKey(editingKey.key, editForm);\n handleCloseEdit();\n } catch (error) {\n console.error('Failed to update key:', error);\n } finally {\n setEditSubmitting(false);\n }\n };\n\n const copyToClipboard = (text: string) => {\n navigator.clipboard.writeText(text);\n };\n\n return (\n <>\n <Paper sx={{ mb: 2 }}>\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" p={2}>\n <Typography variant=\"h6\">Virtual Keys</Typography>\n <Button\n variant=\"contained\"\n color=\"primary\"\n startIcon={<Add />}\n onClick={() => setGenerateModalOpen(true)}\n >\n Generate New Key\n </Button>\n </Box>\n\n <TableContainer>\n <Table>\n <TableHead>\n <TableRow>\n <TableCell>Alias</TableCell>\n <TableCell>Key</TableCell>\n <TableCell>Created</TableCell>\n <TableCell>Spend</TableCell>\n <TableCell>Budget</TableCell>\n <TableCell>TPM Limit</TableCell>\n <TableCell>Models</TableCell>\n <TableCell align=\"right\">Actions</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n <TableRow>\n <TableCell colSpan={8} align=\"center\">\n <CircularProgress size={24} />\n </TableCell>\n </TableRow>\n ) : keys.length === 0 ? (\n <TableRow>\n <TableCell colSpan={8} align=\"center\">\n <Typography color=\"text.secondary\">No keys found</Typography>\n </TableCell>\n </TableRow>\n ) : (\n keys.map((key) => (\n <TableRow key={key.key}>\n <TableCell>{key.key_alias || '-'}</TableCell>\n <TableCell>\n <Box display=\"flex\" alignItems=\"center\" gap={0.5}>\n <Typography \n variant=\"body2\" \n component=\"code\" \n color=\"primary\"\n sx={{ \n fontFamily: 'monospace', \n backgroundColor: 'background.default', \n px: 1, \n py: 0.5, \n borderRadius: 1,\n maxWidth: '250px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n >\n {showKeyValue === key.key ? key.key : maskKey(key.key)}\n </Typography>\n <IconButton\n size=\"small\"\n onClick={() => setShowKeyValue(showKeyValue === key.key ? null : key.key)}\n >\n {showKeyValue === key.key ? <VisibilityOff /> : <Visibility />}\n </IconButton>\n <IconButton size=\"small\" onClick={() => copyToClipboard(key.key)}>\n <ContentCopy fontSize=\"small\" />\n </IconButton>\n </Box>\n </TableCell>\n <TableCell>{formatDate(key.created_at)}</TableCell>\n <TableCell>${key.spend?.toFixed(4) || '0.00'}</TableCell>\n <TableCell>{key.max_budget ? `$${key.max_budget}` : '-'}</TableCell>\n <TableCell>{key.tpm_limit || '-'}</TableCell>\n <TableCell>\n <Box display=\"flex\" gap={0.5} flexWrap=\"wrap\">\n {key.models?.slice(0, 2).map((model) => (\n <Chip key={model} label={model} size=\"small\" />\n ))}\n {(key.models?.length || 0) > 2 && (\n <Chip label={`+${(key.models?.length || 0) - 2}`} size=\"small\" variant=\"outlined\" />\n )}\n </Box>\n </TableCell>\n <TableCell align=\"right\">\n <IconButton onClick={() => handleOpenEdit(key)}>\n <Edit fontSize=\"small\" />\n </IconButton>\n <IconButton color=\"error\" onClick={() => onDeleteKey(key.key)}>\n <Delete />\n </IconButton>\n </TableCell>\n </TableRow>\n ))\n )}\n </TableBody>\n </Table>\n </TableContainer>\n </Paper>\n\n <Dialog open={generateModalOpen} onClose={handleCloseModal} maxWidth=\"sm\" fullWidth>\n <DialogTitle>{newKeyValue ? 'Key Generated' : 'Generate New Key'}</DialogTitle>\n <DialogContent>\n {newKeyValue ? (\n <Box>\n <Typography variant=\"body2\" color=\"text.secondary\" gutterBottom>\n Copy this key now. You won't be able to see it again.\n </Typography>\n <Box\n display=\"flex\"\n alignItems=\"center\"\n gap={1}\n mt={2}\n p={2}\n sx={{\n backgroundColor: 'grey.100',\n borderRadius: 1,\n }}\n >\n <Typography\n component=\"code\"\n color=\"text.primary\"\n sx={{ fontFamily: 'monospace', wordBreak: 'break-all', flex: 1 }}\n >\n {newKeyValue}\n </Typography>\n <IconButton onClick={() => copyToClipboard(newKeyValue)}>\n <ContentCopy />\n </IconButton>\n </Box>\n </Box>\n ) : (\n <Box display=\"flex\" flexDirection=\"column\" gap={2} mt={1}>\n <TextField\n label=\"Alias\"\n value={formData.alias || ''}\n onChange={(e) => setFormData({ ...formData, alias: e.target.value })}\n fullWidth\n />\n <TextField\n select\n label=\"Duration\"\n value={formData.duration || '30d'}\n onChange={(e) => setFormData({ ...formData, duration: e.target.value })}\n fullWidth\n >\n <MenuItem value=\"1d\">1 Day</MenuItem>\n <MenuItem value=\"7d\">7 Days</MenuItem>\n <MenuItem value=\"30d\">30 Days</MenuItem>\n <MenuItem value=\"90d\">90 Days</MenuItem>\n <MenuItem value=\"1y\">1 Year</MenuItem>\n </TextField>\n\n {teams.length > 0 && (\n <Autocomplete\n options={teams}\n getOptionLabel={t => t.team_alias || t.team_id}\n value={selectedTeam}\n onChange={(_e, team) =>\n setFormData({ ...formData, team_id: team?.team_id })\n }\n renderInput={params => (\n <TextField\n {...params}\n label=\"Team\"\n helperText=\"Optional: bind this key to a specific team for scoped access\"\n fullWidth\n />\n )}\n />\n )}\n\n {models.length > 0 && (\n <Autocomplete\n multiple\n options={models}\n groupBy={m => m.mode || 'other'}\n getOptionLabel={m => m.model_name}\n value={selectedModels}\n onChange={(_e, selected) =>\n setFormData({ ...formData, models: selected.map(m => m.model_name) })\n }\n renderOption={(props, m) => (\n <li {...props}>\n {m.model_name}\n {m.supports_function_calling && ' \uD83D\uDD27'}\n {m.supports_vision && ' \uD83D\uDC41\uFE0F'}\n </li>\n )}\n renderInput={params => (\n <TextField {...params} label=\"Models\" fullWidth />\n )}\n />\n )}\n\n <TextField\n label=\"Max Budget (USD)\"\n type=\"number\"\n value={formData.max_budget ?? ''}\n onChange={(e) =>\n setFormData({ ...formData, max_budget: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n <TextField\n label=\"TPM Limit\"\n type=\"number\"\n value={formData.tpm_limit ?? ''}\n onChange={(e) =>\n setFormData({ ...formData, tpm_limit: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n </Box>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleCloseModal}>{newKeyValue ? 'Done' : 'Cancel'}</Button>\n {!newKeyValue && (\n <Button\n onClick={handleGenerate}\n variant=\"contained\"\n color=\"primary\"\n disabled={submitting || !canGenerate}\n >\n {submitting ? <CircularProgress size={24} /> : 'Generate'}\n </Button>\n )}\n {newKeyValue && (\n <Button onClick={handleCloseModal} variant=\"contained\" color=\"success\">\n Done\n </Button>\n )}\n </DialogActions>\n </Dialog>\n\n <Dialog open={!!editingKey} onClose={handleCloseEdit} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Edit Key</DialogTitle>\n <DialogContent>\n {editingKey && (\n <Box display=\"flex\" flexDirection=\"column\" gap={2} mt={1}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n <code style={{ fontFamily: 'monospace', color: 'inherit' }}>{maskKey(editingKey.key)}</code>\n </Typography>\n <TextField\n label=\"Alias\"\n value={editForm.key_alias || ''}\n onChange={(e) => setEditForm({ ...editForm, key_alias: e.target.value })}\n fullWidth\n />\n\n {models.length > 0 && (\n <Autocomplete\n multiple\n options={models}\n groupBy={m => m.mode || 'other'}\n getOptionLabel={m => m.model_name}\n value={editSelectedModels}\n onChange={(_e, selected) =>\n setEditForm({ ...editForm, models: selected.map(m => m.model_name) })\n }\n renderInput={params => (\n <TextField {...params} label=\"Models\" fullWidth />\n )}\n />\n )}\n\n <TextField\n label=\"Max Budget (USD)\"\n type=\"number\"\n value={editForm.max_budget ?? ''}\n onChange={(e) =>\n setEditForm({ ...editForm, max_budget: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n <TextField\n label=\"TPM Limit\"\n type=\"number\"\n value={editForm.tpm_limit ?? ''}\n onChange={(e) =>\n setEditForm({ ...editForm, tpm_limit: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n <TextField\n label=\"RPM Limit\"\n type=\"number\"\n value={editForm.rpm_limit ?? ''}\n onChange={(e) =>\n setEditForm({ ...editForm, rpm_limit: e.target.value ? Number(e.target.value) : undefined })\n }\n fullWidth\n />\n </Box>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleCloseEdit}>Cancel</Button>\n <Button onClick={handleUpdate} variant=\"contained\" color=\"primary\" disabled={editSubmitting}>\n {editSubmitting ? <CircularProgress size={24} /> : 'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n </>\n );\n};\n", "import React, { useMemo, useState } from 'react';\nimport {\n Paper,\n Box,\n Typography,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n Grid,\n CircularProgress,\n Tabs,\n Tab,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TableRow,\n Chip,\n LinearProgress,\n} from '@mui/material';\nimport {\n AreaChart,\n Area,\n BarChart,\n Bar,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n Legend,\n} from 'recharts';\nimport {\n DateRange,\n UsageMetrics,\n ModelInfo,\n UsageModelBreakdown,\n UsageKeyBreakdown,\n} from '../types';\n\ninterface UsageStatsProps {\n usage: UsageMetrics | null;\n models: ModelInfo[];\n dateRange: DateRange;\n onDateRangeChange: (range: DateRange) => void;\n loading: boolean;\n}\n\ntype DatePreset = 'today' | '7d' | '30d';\ntype TabKey = 'costs' | 'models' | 'keys';\n\nconst fmtUsd = (n: number) => `$${(n ?? 0).toFixed(n < 1 ? 4 : 2)}`;\nconst fmtInt = (n: number) => (n ?? 0).toLocaleString();\nconst fmtPct = (n: number) => `${(n * 100).toFixed(1)}%`;\n\nconst KpiCard: React.FC<{ label: string; value: string; hint?: string }> = ({ label, value, hint }) => (\n <Paper variant=\"outlined\" sx={{ p: 2, height: '100%' }}>\n <Typography variant=\"caption\" color=\"text.secondary\">{label}</Typography>\n <Typography variant=\"h5\" sx={{ mt: 0.5 }}>{value}</Typography>\n {hint ? <Typography variant=\"caption\" color=\"text.secondary\">{hint}</Typography> : null}\n </Paper>\n);\n\nexport const UsageStats: React.FC<UsageStatsProps> = ({\n usage,\n models,\n dateRange,\n onDateRangeChange,\n loading,\n}) => {\n const [selectedModel, setSelectedModel] = useState<string>('all');\n const [tab, setTab] = useState<TabKey>('costs');\n\n // Derive selected preset from dateRange to keep it in sync\n // Check order matters: today (0 days), then 7d (1-7 days), then 30d (8+ days)\n const selectedPreset = useMemo(() => {\n const start = dateRange.start;\n const end = dateRange.end;\n // Same day = exactly 'today' (diffDays = 0)\n // If user picks 1 day range (yesterday-today, etc.), that's a 7-day period\n if (start.toDateString() === end.toDateString()) return 'today';\n const diffMs = end.getTime() - start.getTime();\n const diffDays = Math.ceil(diffMs / (1000 * 60 * 60 * 24));\n if (diffDays <= 7) return '7d';\n return '30d';\n }, [dateRange]);\n\n const handlePresetChange = (preset: DatePreset) => {\n const end = new Date();\n const start = new Date();\n if (preset === 'today') start.setHours(0, 0, 0, 0);\n else if (preset === '7d') start.setDate(start.getDate() - 7);\n else if (preset === '30d') start.setDate(start.getDate() - 30);\n onDateRangeChange({ start, end });\n };\n\n const todayRows = useMemo(() => {\n const rows = usage?.daily_by_model ?? [];\n if (rows.length === 0) return [];\n // Pick the most recent date present in the data \u2014 that's the latest\n // \"current day\" the proxy has aggregated, even if today has no traffic yet.\n const latestDate = rows.map(r => r.date).sort().slice(-1)[0];\n return rows\n .filter(r => r.date === latestDate)\n .map(r => ({\n model: r.model,\n promptTokens: r.prompt_tokens,\n completionTokens: r.completion_tokens,\n }))\n .filter(r => r.promptTokens + r.completionTokens > 0)\n .sort((a, b) => (b.promptTokens + b.completionTokens) - (a.promptTokens + a.completionTokens));\n }, [usage]);\n\n const todayLabel = useMemo(() => {\n const rows = usage?.daily_by_model ?? [];\n if (rows.length === 0) return null;\n return rows.map(r => r.date).sort().slice(-1)[0];\n }, [usage]);\n\n const dailyData = useMemo(\n () =>\n (usage?.daily_usage ?? []).map(d => ({\n date: d.date,\n spend: d.spend,\n promptTokens: d.prompt_tokens,\n completionTokens: d.completion_tokens,\n totalTokens: d.total_tokens,\n apiRequests: d.api_requests,\n successfulRequests: d.successful_requests,\n failedRequests: d.failed_requests,\n })),\n [usage],\n );\n\n const modelRows = useMemo(() => {\n const entries = Object.entries<UsageModelBreakdown>(usage?.usage_by_model ?? {}).map(([model, d]) => ({\n model,\n spend: d.total_spend,\n promptTokens: d.prompt_tokens,\n completionTokens: d.completion_tokens,\n totalTokens: d.total_tokens,\n apiRequests: d.api_requests,\n successfulRequests: d.successful_requests,\n failedRequests: d.failed_requests,\n successRate: d.api_requests > 0 ? d.successful_requests / d.api_requests : 0,\n }));\n return selectedModel === 'all' ? entries : entries.filter(e => e.model === selectedModel);\n }, [usage, selectedModel]);\n\n const keyRows = useMemo(\n () =>\n Object.entries<UsageKeyBreakdown>(usage?.usage_by_key ?? {}).map(([keyHash, d]) => ({\n keyHash,\n keyAlias: d.key_alias ?? keyHash.slice(0, 8),\n teamId: d.team_id ?? null,\n models: d.models,\n spend: d.total_spend,\n totalTokens: d.total_tokens,\n promptTokens: d.prompt_tokens,\n completionTokens: d.completion_tokens,\n apiRequests: d.api_requests,\n successfulRequests: d.successful_requests,\n failedRequests: d.failed_requests,\n successRate: d.api_requests > 0 ? d.successful_requests / d.api_requests : 0,\n })),\n [usage],\n );\n\n const totalRequests = usage?.api_requests ?? 0;\n const overallSuccessRate = totalRequests > 0 ? (usage?.successful_requests ?? 0) / totalRequests : 0;\n\n if (loading) {\n return (\n <Paper sx={{ p: 2 }}>\n <Box display=\"flex\" justifyContent=\"center\" p={4}>\n <CircularProgress />\n </Box>\n </Paper>\n );\n }\n\n return (\n <Paper sx={{ p: 2 }}>\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={2} flexWrap=\"wrap\" gap={2}>\n <Typography variant=\"h6\">Usage Analytics</Typography>\n <Box display=\"flex\" gap={2} alignItems=\"center\" flexWrap=\"wrap\">\n <FormControl size=\"small\" sx={{ minWidth: 140 }}>\n <InputLabel>Period</InputLabel>\n <Select\n value={selectedPreset}\n label=\"Period\"\n onChange={e => handlePresetChange(e.target.value as DatePreset)}\n >\n <MenuItem value=\"today\">Today</MenuItem>\n <MenuItem value=\"7d\">Last 7 days</MenuItem>\n <MenuItem value=\"30d\">Last 30 days</MenuItem>\n </Select>\n </FormControl>\n {tab === 'models' && (\n <FormControl size=\"small\" sx={{ minWidth: 180 }}>\n <InputLabel>Model</InputLabel>\n <Select\n value={selectedModel}\n label=\"Model\"\n onChange={e => setSelectedModel(e.target.value)}\n >\n <MenuItem value=\"all\">All Models</MenuItem>\n {models.map(m => (\n <MenuItem key={m.model_name} value={m.model_name}>\n {m.model_name}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n )}\n </Box>\n </Box>\n\n <Grid container spacing={2} sx={{ mb: 2 }}>\n <Grid item xs={6} sm={3}>\n <KpiCard label=\"Total Spend\" value={fmtUsd(usage?.total_spend ?? 0)} />\n </Grid>\n <Grid item xs={6} sm={3}>\n <KpiCard label=\"Total Requests\" value={fmtInt(totalRequests)} hint={`${fmtInt(usage?.failed_requests ?? 0)} failed`} />\n </Grid>\n <Grid item xs={6} sm={3}>\n <KpiCard label=\"Success Rate\" value={totalRequests > 0 ? fmtPct(overallSuccessRate) : '\u2014'} />\n </Grid>\n <Grid item xs={6} sm={3}>\n <KpiCard\n label=\"Total Tokens\"\n value={fmtInt(usage?.total_tokens ?? 0)}\n hint={`${fmtInt(usage?.prompt_tokens ?? 0)} in \u00B7 ${fmtInt(usage?.completion_tokens ?? 0)} out`}\n />\n </Grid>\n </Grid>\n\n <Tabs value={tab} onChange={(_, v) => setTab(v as TabKey)} sx={{ mb: 2 }}>\n <Tab value=\"costs\" label=\"Costs\" />\n <Tab value=\"models\" label=\"Model Activity\" />\n <Tab value=\"keys\" label=\"Key Activity\" />\n </Tabs>\n\n {tab === 'costs' && (\n <Grid container spacing={3}>\n <Grid item xs={12} md={6}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Daily Spend\n </Typography>\n <Box height={260}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={dailyData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"date\" tick={{ fontSize: 12 }} />\n <YAxis tick={{ fontSize: 12 }} tickFormatter={v => `$${v.toFixed(2)}`} />\n <Tooltip formatter={(value: number) => [`$${value.toFixed(4)}`, 'Spend']} />\n <Area type=\"monotone\" dataKey=\"spend\" stroke=\"#8884d8\" fill=\"#8884d8\" fillOpacity={0.3} />\n </AreaChart>\n </ResponsiveContainer>\n </Box>\n </Grid>\n <Grid item xs={12} md={6}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Daily Requests\n </Typography>\n <Box height={260}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={dailyData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"date\" tick={{ fontSize: 12 }} />\n <YAxis tick={{ fontSize: 12 }} />\n <Tooltip />\n <Legend />\n <Bar dataKey=\"successfulRequests\" name=\"Successful\" fill=\"#82ca9d\" stackId=\"r\" />\n <Bar dataKey=\"failedRequests\" name=\"Failed\" fill=\"#e57373\" stackId=\"r\" />\n </BarChart>\n </ResponsiveContainer>\n </Box>\n </Grid>\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n {todayLabel ? `Tokens In / Out by Model \u2014 ${todayLabel}` : 'Tokens In / Out by Model \u2014 Today'}\n </Typography>\n <Box height={300}>\n {todayRows.length === 0 ? (\n <Box display=\"flex\" alignItems=\"center\" justifyContent=\"center\" height=\"100%\">\n <Typography color=\"text.secondary\">No token activity for the latest day</Typography>\n </Box>\n ) : (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={todayRows} layout=\"vertical\" margin={{ left: 60 }}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis type=\"number\" tick={{ fontSize: 12 }} tickFormatter={fmtInt} />\n <YAxis type=\"category\" dataKey=\"model\" tick={{ fontSize: 11 }} width={180} />\n <Tooltip formatter={(value: number) => fmtInt(value)} />\n <Legend />\n <Bar dataKey=\"promptTokens\" name=\"Input (prompt)\" fill=\"#8884d8\" stackId=\"io\" />\n <Bar dataKey=\"completionTokens\" name=\"Output (completion)\" fill=\"#82ca9d\" stackId=\"io\" />\n </BarChart>\n </ResponsiveContainer>\n )}\n </Box>\n </Grid>\n </Grid>\n )}\n\n {tab === 'models' && (\n <Grid container spacing={3}>\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Tokens by Model\n </Typography>\n <Box height={260}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <BarChart data={modelRows}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"model\" tick={{ fontSize: 10 }} interval={0} angle={-15} textAnchor=\"end\" height={60} />\n <YAxis tick={{ fontSize: 12 }} />\n <Tooltip />\n <Legend />\n <Bar dataKey=\"promptTokens\" name=\"Prompt\" fill=\"#8884d8\" stackId=\"t\" />\n <Bar dataKey=\"completionTokens\" name=\"Completion\" fill=\"#82ca9d\" stackId=\"t\" />\n </BarChart>\n </ResponsiveContainer>\n </Box>\n </Grid>\n <Grid item xs={12}>\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Model</TableCell>\n <TableCell align=\"right\">Spend</TableCell>\n <TableCell align=\"right\">Requests</TableCell>\n <TableCell align=\"right\">Success</TableCell>\n <TableCell align=\"right\">Failed</TableCell>\n <TableCell align=\"right\">Prompt</TableCell>\n <TableCell align=\"right\">Completion</TableCell>\n <TableCell sx={{ minWidth: 120 }}>Success rate</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {modelRows.length === 0 ? (\n <TableRow><TableCell colSpan={8} align=\"center\">No model activity</TableCell></TableRow>\n ) : modelRows\n .sort((a, b) => b.spend - a.spend || b.totalTokens - a.totalTokens)\n .map(r => (\n <TableRow key={r.model}>\n <TableCell>{r.model}</TableCell>\n <TableCell align=\"right\">{fmtUsd(r.spend)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.apiRequests)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.successfulRequests)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.failedRequests)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.promptTokens)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.completionTokens)}</TableCell>\n <TableCell>\n {r.apiRequests > 0 ? (\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <LinearProgress\n variant=\"determinate\"\n value={r.successRate * 100}\n sx={{ flex: 1, height: 6, borderRadius: 3 }}\n />\n <Typography variant=\"caption\">{fmtPct(r.successRate)}</Typography>\n </Box>\n ) : '\u2014'}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n </Grid>\n </Grid>\n )}\n\n {tab === 'keys' && (\n <TableContainer component={Paper} variant=\"outlined\">\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>Key</TableCell>\n <TableCell>Models</TableCell>\n <TableCell align=\"right\">Spend</TableCell>\n <TableCell align=\"right\">Requests</TableCell>\n <TableCell align=\"right\">Tokens</TableCell>\n <TableCell align=\"right\">Failed</TableCell>\n <TableCell sx={{ minWidth: 120 }}>Success rate</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {keyRows.length === 0 ? (\n <TableRow><TableCell colSpan={7} align=\"center\">No key activity</TableCell></TableRow>\n ) : keyRows\n .sort((a, b) => b.spend - a.spend || b.apiRequests - a.apiRequests)\n .map(r => (\n <TableRow key={r.keyHash}>\n <TableCell>\n <Typography variant=\"body2\">{r.keyAlias}</Typography>\n {r.teamId ? (\n <Typography variant=\"caption\" color=\"text.secondary\">team: {r.teamId}</Typography>\n ) : null}\n </TableCell>\n <TableCell>\n <Box display=\"flex\" gap={0.5} flexWrap=\"wrap\">\n {r.models.map(m => (\n <Chip key={m} label={m} size=\"small\" variant=\"outlined\" />\n ))}\n </Box>\n </TableCell>\n <TableCell align=\"right\">{fmtUsd(r.spend)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.apiRequests)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.totalTokens)}</TableCell>\n <TableCell align=\"right\">{fmtInt(r.failedRequests)}</TableCell>\n <TableCell>\n {r.apiRequests > 0 ? (\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <LinearProgress\n variant=\"determinate\"\n value={r.successRate * 100}\n sx={{ flex: 1, height: 6, borderRadius: 3 }}\n />\n <Typography variant=\"caption\">{fmtPct(r.successRate)}</Typography>\n </Box>\n ) : '\u2014'}\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n )}\n </Paper>\n );\n};\n", "import React, { useState } from 'react';\nimport {\n Paper,\n Box,\n Typography,\n LinearProgress,\n Chip,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TableContainer,\n Collapse,\n IconButton,\n CircularProgress,\n} from '@mui/material';\nimport { ExpandMore, ExpandLess, Group } from '@mui/icons-material';\nimport {\n AreaChart,\n Area,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n} from 'recharts';\nimport { TeamInfo, UsageMetrics, DateRange } from '../types';\n\ninterface TeamCardProps {\n team: TeamInfo;\n usage: UsageMetrics | null;\n usageLoading: boolean;\n}\n\nconst TeamCard: React.FC<TeamCardProps> = ({ team, usage, usageLoading }) => {\n const [expanded, setExpanded] = useState(false);\n\n const budget = team.max_budget ?? 0;\n const spend = team.spend ?? 0;\n const budgetPct = budget > 0 ? Math.min((spend / budget) * 100, 100) : 0;\n const isOver = budget > 0 && spend >= budget;\n const isNear = budget > 0 && spend >= budget * 0.8 && !isOver;\n\n const dailyData = usage?.daily_usage?.map(d => ({ date: d.date, spend: d.spend })) ?? [];\n\n return (\n <Paper variant=\"outlined\" sx={{ p: 2, mb: 2 }}>\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <Group color=\"action\" />\n <Box flexGrow={1}>\n <Typography variant=\"subtitle1\" fontWeight={600}>\n {team.team_alias ?? team.team_id}\n </Typography>\n {team.models?.length ? (\n <Box display=\"flex\" gap={0.5} flexWrap=\"wrap\" mt={0.5}>\n {team.models.map(m => (\n <Chip key={m} label={m} size=\"small\" variant=\"outlined\" />\n ))}\n </Box>\n ) : (\n <Typography variant=\"caption\" color=\"text.secondary\">All models</Typography>\n )}\n </Box>\n <IconButton size=\"small\" onClick={() => setExpanded(e => !e)}>\n {expanded ? <ExpandLess /> : <ExpandMore />}\n </IconButton>\n </Box>\n\n {budget > 0 && (\n <Box mt={1.5}>\n <Box display=\"flex\" justifyContent=\"space-between\" mb={0.5}>\n <Typography variant=\"body2\">\n ${spend.toFixed(2)} / ${budget.toFixed(2)}\n </Typography>\n {isOver && <Chip label=\"Over Budget\" size=\"small\" color=\"error\" />}\n {isNear && <Chip label=\"Near Limit\" size=\"small\" color=\"warning\" />}\n </Box>\n <LinearProgress\n variant=\"determinate\"\n value={budgetPct}\n color={isOver ? 'error' : isNear ? 'warning' : 'primary'}\n sx={{ height: 6, borderRadius: 1 }}\n />\n </Box>\n )}\n\n <Collapse in={expanded}>\n <Box mt={2}>\n {usageLoading ? (\n <Box display=\"flex\" justifyContent=\"center\" p={2}>\n <CircularProgress size={24} />\n </Box>\n ) : dailyData.length > 0 ? (\n <>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Daily Spend\n </Typography>\n <Box height={160}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={dailyData}>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis dataKey=\"date\" tick={{ fontSize: 11 }} />\n <YAxis tick={{ fontSize: 11 }} tickFormatter={v => `$${v.toFixed(2)}`} />\n <Tooltip formatter={(v: number) => [`$${v.toFixed(4)}`, 'Spend']} />\n <Area type=\"monotone\" dataKey=\"spend\" stroke=\"#8884d8\" fill=\"#8884d8\" fillOpacity={0.3} />\n </AreaChart>\n </ResponsiveContainer>\n </Box>\n </>\n ) : null}\n\n {team.members_with_roles?.length ? (\n <Box mt={2}>\n <Typography variant=\"subtitle2\" color=\"text.secondary\" gutterBottom>\n Members\n </Typography>\n <TableContainer>\n <Table size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>User</TableCell>\n <TableCell>Role</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {team.members_with_roles.map(m => (\n <TableRow key={m.user_id}>\n <TableCell sx={{ fontFamily: 'monospace', fontSize: 12 }}>{m.user_id}</TableCell>\n <TableCell>\n <Chip\n label={m.role}\n size=\"small\"\n color={m.role === 'admin' ? 'primary' : 'default'}\n />\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </TableContainer>\n </Box>\n ) : null}\n </Box>\n </Collapse>\n </Paper>\n );\n};\n\ninterface TeamUsageProps {\n teams: TeamInfo[];\n loading: boolean;\n dateRange: DateRange;\n getTeamUsage: (teamId: string) => UsageMetrics | null;\n getTeamUsageLoading: (teamId: string) => boolean;\n}\n\nexport const TeamUsage: React.FC<TeamUsageProps> = ({\n teams,\n loading,\n getTeamUsage,\n getTeamUsageLoading,\n}) => {\n if (loading) {\n return (\n <Paper sx={{ p: 2 }}>\n <LinearProgress />\n </Paper>\n );\n }\n\n if (!teams.length) {\n return (\n <Paper sx={{ p: 2 }}>\n <Box display=\"flex\" alignItems=\"center\" gap={1}>\n <Group color=\"disabled\" />\n <Typography color=\"text.secondary\" variant=\"body2\">\n No team membership found in LiteLLM for this account.\n </Typography>\n </Box>\n </Paper>\n );\n }\n\n return (\n <Box>\n <Typography variant=\"h6\" mb={1}>Teams</Typography>\n {teams.map(team => (\n <TeamCard\n key={team.team_id}\n team={team}\n usage={getTeamUsage(team.team_id)}\n usageLoading={getTeamUsageLoading(team.team_id)}\n />\n ))}\n </Box>\n );\n};\n", "import React, { useState, useCallback, useMemo } from 'react';\nimport { Grid, Box, Snackbar, Alert, CircularProgress, Typography, Paper } from '@mui/material';\nimport { useAsync, useAsyncRetry } from 'react-use';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { DashboardHeader } from './DashboardHeader';\nimport { KeysTable } from './KeysTable';\nimport { UsageStats } from './UsageStats';\nimport { TeamUsage } from './TeamUsage';\nimport { liteLlmApiRef } from '../api';\nimport { DateRange, GenerateKeyRequest, GenerateKeyResponse, UpdateKeyRequest, UsageMetrics } from '../types';\n\nexport const LiteLLMPage: React.FC = () => {\n const api = useApi(liteLlmApiRef);\n\n const [dateRange, setDateRange] = useState<DateRange>(() => {\n const end = new Date();\n const start = new Date();\n start.setDate(start.getDate() - 7);\n return { start, end };\n });\n\n const [snackbar, setSnackbar] = useState<{ message: string; severity: 'success' | 'warning' | 'error' } | null>(null);\n\n // Team usage cache: teamId -> UsageMetrics\n const [teamUsageCache, setTeamUsageCache] = useState<Record<string, UsageMetrics | null>>({});\n const [teamUsageLoading, setTeamUsageLoading] = useState<Record<string, boolean>>({});\n\n const { value: userInfo, loading: userLoading, error: userError } = useAsync(\n () => api.getUserInfo(),\n [api],\n );\n\n const { value: keys, loading: keysLoading, retry: refreshKeys } = useAsyncRetry(\n async () => {\n try {\n return await api.listKeys();\n } catch (e: any) {\n setSnackbar({ message: `Failed to load keys: ${e.message}`, severity: 'error' });\n return [];\n }\n },\n [api],\n );\n\n const { value: allModels, loading: modelsLoading } = useAsync(\n () => api.listModels().catch(() => []),\n [api],\n );\n\n const { value: allTeams, loading: teamsLoading } = useAsync(\n () => api.getTeams().catch(() => []),\n [api],\n );\n\n // Filter to teams the current user belongs to\n const teams = useMemo(() => {\n if (!allTeams?.length) return [];\n if (!userInfo) return allTeams;\n const userId = userInfo.user_id;\n if (userInfo.teams?.length) {\n return allTeams.filter(t => userInfo.teams!.includes(t.team_id));\n }\n const byMembership = allTeams.filter(t =>\n t.members_with_roles?.some(m => m.user_id === userId),\n );\n return byMembership.length > 0 ? byMembership : allTeams;\n }, [allTeams, userInfo]);\n\n const { value: usage, loading: usageLoading } = useAsync(async () => {\n const startDate = dateRange.start.toISOString().split('T')[0];\n const endDate = dateRange.end.toISOString().split('T')[0];\n return api.getUsage(startDate, endDate);\n }, [api, dateRange]);\n\n // Fetch team usage on demand when a team card is expanded\n const loadTeamUsage = useCallback(async (teamId: string) => {\n if (teamUsageCache[teamId] !== undefined || teamUsageLoading[teamId]) return;\n setTeamUsageLoading(prev => ({ ...prev, [teamId]: true }));\n try {\n const startDate = dateRange.start.toISOString().split('T')[0];\n const endDate = dateRange.end.toISOString().split('T')[0];\n const data = await api.getTeamUsage(teamId, startDate, endDate);\n setTeamUsageCache(prev => ({ ...prev, [teamId]: data }));\n } catch {\n setTeamUsageCache(prev => ({ ...prev, [teamId]: null }));\n } finally {\n setTeamUsageLoading(prev => ({ ...prev, [teamId]: false }));\n }\n }, [api, dateRange, teamUsageCache, teamUsageLoading]);\n\n // Models available for key generation: intersection of all models with user-level\n // and team-level restrictions. If a user has no model restrictions, all models are allowed.\n const allowedModels = useMemo(() => {\n if (!allModels?.length) return [];\n const userModels = userInfo?.models;\n const teamModels = teams?.flatMap(t => t.models ?? []);\n const hasUserRestriction = userModels && userModels.length > 0;\n const hasTeamRestriction = teamModels && teamModels.length > 0;\n if (!hasUserRestriction && !hasTeamRestriction) return allModels;\n const allowed = new Set([\n ...(hasUserRestriction ? userModels! : allModels.map(m => m.model_name)),\n ...(hasTeamRestriction ? teamModels! : []),\n ]);\n return allModels.filter(m => allowed.has(m.model_name));\n }, [allModels, userInfo, teams]);\n\n const handleGenerateKey = useCallback(\n async (request: GenerateKeyRequest): Promise<GenerateKeyResponse> => {\n const response = await api.generateKey(request);\n setSnackbar({ message: 'Key generated successfully', severity: 'success' });\n refreshKeys();\n return response;\n },\n [api, refreshKeys],\n );\n\n const handleUpdateKey = useCallback(\n async (keyId: string, request: UpdateKeyRequest) => {\n try {\n await api.updateKey(keyId, request);\n setSnackbar({ message: 'Key updated successfully', severity: 'success' });\n refreshKeys();\n } catch (e: any) {\n setSnackbar({ message: `Failed to update key: ${e.message}`, severity: 'error' });\n throw e;\n }\n },\n [api, refreshKeys],\n );\n\n const handleDeleteKey = useCallback(\n async (keyId: string) => {\n try {\n await api.deleteKey(keyId);\n setSnackbar({ \n message: 'Key revoked successfully', \n severity: 'success' \n });\n refreshKeys();\n } catch (e: any) {\n // Handle \"already deleted\" response gracefully (idempotent)\n // If backend returns 200 with success=true, it means key was already gone\n if (e.body?.success && (e.body?.message?.includes('already deleted') || e.body?.message?.includes('never existed'))) {\n setSnackbar({ \n message: 'Key was already deleted', \n severity: 'warning' \n });\n refreshKeys(); // Still refresh to ensure UI consistency\n return;\n }\n setSnackbar({ \n message: `Failed to revoke key: ${e.message}`, \n severity: 'error' \n });\n } finally {\n refreshKeys();\n }\n },\n [api, refreshKeys],\n );\n\n const isInitialLoading = userLoading && !userInfo;\n\n if (isInitialLoading) {\n return (\n <Box display=\"flex\" justifyContent=\"center\" alignItems=\"center\" minHeight=\"50vh\">\n <CircularProgress />\n </Box>\n );\n }\n\n // User exists in Backstage but has no LiteLLM account\n if (userError || !userInfo) {\n const isProvisioningEnabled = (userError as any)?.body?.provisioning === true;\n const hint = (userError as any)?.body?.hint;\n return (\n <Box p={3}>\n <Paper sx={{ p: 3 }}>\n <Typography variant=\"h6\" gutterBottom>Account not provisioned</Typography>\n <Typography color=\"text.secondary\" paragraph>\n Your Backstage account is not linked to a LiteLLM user.\n </Typography>\n {hint ? (\n <Typography variant=\"body2\" color=\"text.secondary\">{hint}</Typography>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {isProvisioningEnabled\n ? 'Auto-provisioning is enabled but failed. Check the backend logs.'\n : 'Set litellm.provisioning.enabled: true in app-config.yaml to enable auto-provisioning, or ask your administrator to create the account manually.'}\n </Typography>\n )}\n </Paper>\n </Box>\n );\n }\n\n return (\n <Box p={3}>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <DashboardHeader userInfo={userInfo} teams={teams ?? []} loading={userLoading || teamsLoading} />\n </Grid>\n\n <Grid item xs={12}>\n <TeamUsage\n teams={teams ?? []}\n loading={teamsLoading}\n dateRange={dateRange}\n getTeamUsage={teamId => {\n if (teamUsageCache[teamId] === undefined) loadTeamUsage(teamId);\n return teamUsageCache[teamId] ?? null;\n }}\n getTeamUsageLoading={teamId => teamUsageLoading[teamId] ?? false}\n />\n </Grid>\n\n <Grid item xs={12}>\n <KeysTable\n keys={keys ?? []}\n models={allowedModels}\n teams={teams ?? []}\n loading={keysLoading || modelsLoading}\n onGenerateKey={handleGenerateKey}\n onUpdateKey={handleUpdateKey}\n onDeleteKey={handleDeleteKey}\n />\n </Grid>\n\n <Grid item xs={12}>\n <UsageStats\n usage={usage ?? null}\n models={allModels ?? []}\n dateRange={dateRange}\n onDateRangeChange={setDateRange}\n loading={usageLoading}\n />\n </Grid>\n </Grid>\n\n <Snackbar\n open={!!snackbar}\n autoHideDuration={5000}\n onClose={() => setSnackbar(null)}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n >\n {snackbar ? (\n <Alert severity={snackbar.severity} onClose={() => setSnackbar(null)}>\n {snackbar.message}\n </Alert>\n ) : undefined}\n </Snackbar>\n </Box>\n );\n};\n", "import React from 'react';\nimport { TrendingUp as TrendingUpIcon } from '@mui/icons-material';\nimport {\n createFrontendPlugin,\n ApiBlueprint,\n PageBlueprint,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { liteLlmApiRef, LiteLlmApi } from './api';\n\nconst liteLlmApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\n api: liteLlmApiRef,\n deps: { fetchApi: fetchApiRef },\n factory: ({ fetchApi }) => new LiteLlmApi(fetchApi),\n }),\n});\n\nconst liteLlmPage = PageBlueprint.make({\n params: {\n path: '/litellm',\n title: 'LiteLLM',\n icon: <TrendingUpIcon />,\n loader: async () => {\n const { LiteLLMPage } = await import('./components/LiteLLMPage');\n return <LiteLLMPage />;\n },\n },\n});\n\nexport const litellmPlugin = createFrontendPlugin({\n pluginId: 'litellm',\n extensions: [liteLlmApi, liteLlmPage],\n});\n", "export { litellmPlugin } from './plugin';\nexport { LiteLLMPage } from './components/LiteLLMPage';\nexport { DashboardHeader } from './components/DashboardHeader';\nexport { KeysTable } from './components/KeysTable';\nexport { UsageStats } from './components/UsageStats';\nexport { TeamUsage } from './components/TeamUsage';\nexport { LiteLlmApi, liteLlmApiRef } from './api';\nexport type { LiteLlmApiInterface } from './api';\nexport * from './types';\n"],
5
+ "mappings": "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",
6
6
  "names": ["React", "Paper", "Box", "Typography", "Chip", "React", "useState", "Paper", "Box", "Typography", "MenuItem", "CircularProgress", "Table", "TableBody", "TableCell", "TableContainer", "TableHead", "TableRow", "Chip", "LinearProgress", "React", "useState", "Paper", "Box", "Typography", "LinearProgress", "Chip", "Table", "TableBody", "TableCell", "TableHead", "TableRow", "TableContainer", "IconButton", "CircularProgress", "AreaChart", "Area", "XAxis", "YAxis", "CartesianGrid", "Tooltip", "ResponsiveContainer", "React", "useState", "useMemo", "Grid", "Box", "CircularProgress", "Typography", "Paper", "React", "LiteLLMPage"]
7
7
  }
package/dist/plugin.d.ts CHANGED
@@ -1 +1,52 @@
1
- export declare const litellmPlugin: import("@backstage/frontend-plugin-api").BackstagePlugin<{}, {}, {}>;
1
+ import React from 'react';
2
+ export declare const litellmPlugin: import("@backstage/frontend-plugin-api").OverridableFrontendPlugin<{}, {}, {
3
+ "api:litellm": import("@backstage/frontend-plugin-api").OverridableExtensionDefinition<{
4
+ kind: "api";
5
+ name: undefined;
6
+ config: {};
7
+ configInput: {};
8
+ output: import("@backstage/frontend-plugin-api").ExtensionDataRef<import("@backstage/frontend-plugin-api").AnyApiFactory, "core.api.factory", {}>;
9
+ inputs: {};
10
+ params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: import("@backstage/frontend-plugin-api").ApiFactory<TApi, TImpl, TDeps>) => import("@backstage/frontend-plugin-api").ExtensionBlueprintParams<import("@backstage/frontend-plugin-api").AnyApiFactory>;
11
+ }>;
12
+ "page:litellm": import("@backstage/frontend-plugin-api").OverridableExtensionDefinition<{
13
+ kind: "page";
14
+ name: undefined;
15
+ config: {
16
+ path: string | undefined;
17
+ title: string | undefined;
18
+ };
19
+ configInput: {
20
+ path?: string | undefined;
21
+ title?: string | undefined;
22
+ };
23
+ output: import("@backstage/frontend-plugin-api").ExtensionDataRef<string, "core.routing.path", {}> | import("@backstage/frontend-plugin-api").ExtensionDataRef<import("@backstage/frontend-plugin-api").RouteRef<import("@backstage/frontend-plugin-api").AnyRouteRefParams>, "core.routing.ref", {
24
+ optional: true;
25
+ }> | import("@backstage/frontend-plugin-api").ExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | import("@backstage/frontend-plugin-api").ExtensionDataRef<string, "core.title", {
26
+ optional: true;
27
+ }> | import("@backstage/frontend-plugin-api").ExtensionDataRef<import("@backstage/frontend-plugin-api").IconElement, "core.icon", {
28
+ optional: true;
29
+ }>;
30
+ inputs: {
31
+ pages: import("@backstage/frontend-plugin-api").ExtensionInput<import("@backstage/frontend-plugin-api").ConfigurableExtensionDataRef<React.JSX.Element, "core.reactElement", {}> | import("@backstage/frontend-plugin-api").ConfigurableExtensionDataRef<string, "core.routing.path", {}> | import("@backstage/frontend-plugin-api").ConfigurableExtensionDataRef<import("@backstage/frontend-plugin-api").RouteRef<import("@backstage/frontend-plugin-api").AnyRouteRefParams>, "core.routing.ref", {
32
+ optional: true;
33
+ }> | import("@backstage/frontend-plugin-api").ConfigurableExtensionDataRef<string, "core.title", {
34
+ optional: true;
35
+ }> | import("@backstage/frontend-plugin-api").ConfigurableExtensionDataRef<import("@backstage/frontend-plugin-api").IconElement, "core.icon", {
36
+ optional: true;
37
+ }>, {
38
+ singleton: false;
39
+ optional: false;
40
+ internal: false;
41
+ }>;
42
+ };
43
+ params: {
44
+ path: string;
45
+ title?: string;
46
+ icon?: import("@backstage/frontend-plugin-api").IconElement;
47
+ loader?: () => Promise<React.JSX.Element>;
48
+ routeRef?: import("@backstage/frontend-plugin-api").RouteRef;
49
+ noHeader?: boolean;
50
+ };
51
+ }>;
52
+ }>;