const LITELLM_URL = process.env.LITELLM_INTERNAL_URL ?? "http://litellm.inference.svc:4000"; const LITELLM_MASTER_KEY = process.env.LITELLM_MASTER_KEY!; async function litellmFetch(path: string, init?: RequestInit) { const res = await fetch(`${LITELLM_URL}${path}`, { ...init, headers: { Authorization: `Bearer ${LITELLM_MASTER_KEY}`, "Content-Type": "application/json", ...init?.headers, }, }); if (!res.ok) { throw new Error(`LiteLLM ${path}: ${res.status} ${await res.text()}`); } return res.json(); } export async function getTeamInfo(teamId: string) { return litellmFetch(`/team/info?team_id=${encodeURIComponent(teamId)}`); } export async function getTeamSpendLogs( teamId: string, startDate?: string, endDate?: string ) { const params = new URLSearchParams({ team_id: teamId }); if (startDate) params.set("start_date", startDate); if (endDate) params.set("end_date", endDate); return litellmFetch(`/global/spend/logs?${params}`); } export async function getTeamSpendLogsV2( teamId: string, startDate: string, endDate: string, page: number = 1, pageSize: number = 100 ) { const params = new URLSearchParams({ team_id: teamId, start_date: `${startDate} 00:00:00`, end_date: `${endDate} 23:59:59`, page: String(page), page_size: String(pageSize), }); return litellmFetch(`/spend/logs/v2?${params}`); } /** * Get all teams registered in LiteLLM. * Returns team_id, spend, max_budget, etc. */ export async function listTeams(): Promise { const data = await litellmFetch("/team/list"); // LiteLLM returns either an array or { data: [...] } return Array.isArray(data) ? data : data?.data ?? data?.teams ?? []; } /** * Get LiteLLM health status. */ export async function getLitellmHealth(): Promise<{ healthy: boolean; details?: any; }> { try { const data = await litellmFetch("/health"); return { healthy: true, details: data }; } catch (e: any) { return { healthy: false, details: e.message }; } } /** * Get global spend across all teams for the current month. */ export async function getGlobalSpend(): Promise { try { const data = await litellmFetch("/global/spend"); // LiteLLM returns { spend: number } or similar if (typeof data === "number") return data; return data?.spend ?? data?.total_spend ?? 0; } catch { return 0; } } /** * Fetch per-team spend as a map: teamId → spend (CHF). * Uses /team/list which includes current spend per team. */ export async function getPerTeamSpend(): Promise> { const teams = await listTeams(); const map = new Map(); for (const team of teams) { const id = team.team_id ?? team.id; const spend = team.spend ?? 0; if (id) map.set(id, spend); } return map; }