@acarmisc/backstage-plugin-litellm 0.34.0 → 0.36.0

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.
package/dist/index.esm.js CHANGED
@@ -235,6 +235,10 @@ var init_api = __esm({
235
235
  async listModels() {
236
236
  return this.get("/models");
237
237
  }
238
+ /** Mints (or rotates) the caller's connect-flow key, optionally bound to one of their teams. */
239
+ async connectLocalClient(redirectUri, team) {
240
+ return this.post("/opencode/connect", { redirect_uri: redirectUri, team });
241
+ }
238
242
  async getTeams() {
239
243
  return this.get("/teams");
240
244
  }
@@ -285,6 +289,12 @@ var init_api = __esm({
285
289
  end_date: endDate
286
290
  });
287
291
  }
292
+ async getTeamMemberUsage(teamId, startDate, endDate) {
293
+ return this.get(`/teams/${encodeURIComponent(teamId)}/usage/members`, {
294
+ start_date: startDate,
295
+ end_date: endDate
296
+ });
297
+ }
288
298
  async getConfig() {
289
299
  return this.get("/config");
290
300
  }
@@ -5010,13 +5020,49 @@ function budgetStatValue(hidden, budget) {
5010
5020
  if (budget > 0) return fmtUsd2(budget);
5011
5021
  return "Unlimited";
5012
5022
  }
5013
- var fmtUsd2, TeamCard, TeamUsage;
5023
+ var fmtUsd2, monoSx, MemberUsageTable, TeamCard, TeamUsage;
5014
5024
  var init_TeamUsage = __esm({
5015
5025
  "src/components/TeamUsage.tsx"() {
5016
5026
  "use strict";
5017
5027
  init_ui();
5018
5028
  fmtUsd2 = (n) => `$${(n ?? 0).toFixed(2)}`;
5019
- TeamCard = ({ team, usage, usageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand }) => {
5029
+ monoSx = { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 };
5030
+ MemberUsageTable = ({ usage }) => {
5031
+ const hidden = usage.budget_hidden === true;
5032
+ if (!usage.members.length) {
5033
+ return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "No members or activity in this period." });
5034
+ }
5035
+ return /* @__PURE__ */ jsx15(TableContainer4, { component: Paper8, variant: "outlined", sx: { borderRadius: 1.5 }, children: /* @__PURE__ */ jsxs14(Table4, { size: "small", sx: dataTableSx, "aria-label": "Usage by member", children: [
5036
+ /* @__PURE__ */ jsx15(TableHead4, { children: /* @__PURE__ */ jsxs14(TableRow4, { children: [
5037
+ /* @__PURE__ */ jsx15(TableCell4, { children: "Member" }),
5038
+ !hidden && /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Spend" }),
5039
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Share" }),
5040
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Tokens" }),
5041
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Requests" }),
5042
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Success" }),
5043
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Keys" })
5044
+ ] }) }),
5045
+ /* @__PURE__ */ jsx15(TableBody4, { children: usage.members.map((m) => {
5046
+ const name = m.display_name ?? m.user_email ?? m.user_id;
5047
+ let sub = null;
5048
+ if (m.display_name) sub = m.user_email ?? m.user_id;
5049
+ else if (m.user_email && m.user_id !== m.user_email) sub = m.user_id;
5050
+ return /* @__PURE__ */ jsxs14(TableRow4, { children: [
5051
+ /* @__PURE__ */ jsx15(TableCell4, { children: m.user_id === null ? /* @__PURE__ */ jsx15(MuiTooltip, { title: "Activity of keys that were deleted or have no owner", children: /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", sx: { fontStyle: "italic" }, children: "Unattributed" }) }) : /* @__PURE__ */ jsxs14(Fragment8, { children: [
5052
+ /* @__PURE__ */ jsx15(Typography12, { variant: "body2", children: name }),
5053
+ sub && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", sx: monoSx, children: sub })
5054
+ ] }) }),
5055
+ !hidden && /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: fmtUsd2(m.spend) }),
5056
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: `${m.spend_share_pct.toFixed(m.spend_share_pct > 0 && m.spend_share_pct < 1 ? 1 : 0)}%` }),
5057
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: fmtCompact(m.total_tokens) }),
5058
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: m.api_requests.toLocaleString() }),
5059
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: m.success_rate === null ? "\u2014" : `${m.success_rate.toFixed(0)}%` }),
5060
+ /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: m.user_id === null ? "\u2014" : m.key_count })
5061
+ ] }, m.user_id ?? "__unattributed");
5062
+ }) })
5063
+ ] }) });
5064
+ };
5065
+ TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand }) => {
5020
5066
  const [expanded, setExpanded] = useState9(false);
5021
5067
  const chart = useChartTheme();
5022
5068
  const handleExpandChange = (newExpanded) => {
@@ -5209,6 +5255,10 @@ var init_TeamUsage = __esm({
5209
5255
  team.models?.length ? /* @__PURE__ */ jsx15(Box14, { display: "flex", gap: 0.5, flexWrap: "wrap", children: team.models.map((m) => /* @__PURE__ */ jsx15(TagChip, { label: m, title: m }, m)) }) : /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "All models allowed" })
5210
5256
  ] }),
5211
5257
  renderDailySpendSection(),
5258
+ (memberUsageLoading || memberUsage) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
5259
+ sectionLabel("Usage by member"),
5260
+ memberUsage ? /* @__PURE__ */ jsx15(MemberUsageTable, { usage: memberUsage }) : /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
5261
+ ] }),
5212
5262
  /* @__PURE__ */ jsxs14(Box14, { children: [
5213
5263
  sectionLabel("Members"),
5214
5264
  team.members_with_roles?.length ? /* @__PURE__ */ jsx15(
@@ -5263,6 +5313,8 @@ var init_TeamUsage = __esm({
5263
5313
  loading,
5264
5314
  getTeamUsage,
5265
5315
  getTeamUsageLoading,
5316
+ getTeamMemberUsage,
5317
+ getTeamMemberUsageLoading,
5266
5318
  canManage,
5267
5319
  onEditTeam,
5268
5320
  canCreate,
@@ -5322,6 +5374,8 @@ var init_TeamUsage = __esm({
5322
5374
  team,
5323
5375
  usage: getTeamUsage(team.team_id),
5324
5376
  usageLoading: getTeamUsageLoading(team.team_id),
5377
+ memberUsage: getTeamMemberUsage?.(team.team_id) ?? null,
5378
+ memberUsageLoading: getTeamMemberUsageLoading?.(team.team_id) ?? false,
5325
5379
  canManage,
5326
5380
  onEditTeam,
5327
5381
  canManageMembers: canManageMembers?.(team),
@@ -6134,6 +6188,8 @@ var init_LiteLLMPage = __esm({
6134
6188
  const keyFormOpen = generateDialogOpen || !!keyToEdit;
6135
6189
  const [teamUsageCache, setTeamUsageCache] = useState12({});
6136
6190
  const [teamUsageLoading, setTeamUsageLoading] = useState12({});
6191
+ const [memberUsageCache, setMemberUsageCache] = useState12({});
6192
+ const [memberUsageLoading, setMemberUsageLoading] = useState12({});
6137
6193
  const { value: userInfo, loading: userLoading, error: userError } = useAsync2(
6138
6194
  () => api.getUserInfo(),
6139
6195
  [api]
@@ -6194,6 +6250,8 @@ var init_LiteLLMPage = __esm({
6194
6250
  }
6195
6251
  setTeamUsageCache({});
6196
6252
  setTeamUsageLoading({});
6253
+ setMemberUsageCache({});
6254
+ setMemberUsageLoading({});
6197
6255
  }, [setDateRange, setCurrentPreset]);
6198
6256
  const loadTeamUsage = useCallback4(async (teamId) => {
6199
6257
  if (teamUsageCache[teamId] !== void 0 || teamUsageLoading[teamId]) return;
@@ -6209,6 +6267,20 @@ var init_LiteLLMPage = __esm({
6209
6267
  setTeamUsageLoading((prev) => ({ ...prev, [teamId]: false }));
6210
6268
  }
6211
6269
  }, [api, dateRange, teamUsageCache, teamUsageLoading]);
6270
+ const loadMemberUsage = useCallback4(async (teamId) => {
6271
+ if (memberUsageCache[teamId] !== void 0 || memberUsageLoading[teamId]) return;
6272
+ setMemberUsageLoading((prev) => ({ ...prev, [teamId]: true }));
6273
+ try {
6274
+ const startDate = toLocalDay(dateRange.start);
6275
+ const endDate = toLocalDay(dateRange.end);
6276
+ const data = await api.getTeamMemberUsage(teamId, startDate, endDate);
6277
+ setMemberUsageCache((prev) => ({ ...prev, [teamId]: data }));
6278
+ } catch {
6279
+ setMemberUsageCache((prev) => ({ ...prev, [teamId]: null }));
6280
+ } finally {
6281
+ setMemberUsageLoading((prev) => ({ ...prev, [teamId]: false }));
6282
+ }
6283
+ }, [api, dateRange, memberUsageCache, memberUsageLoading]);
6212
6284
  const allowedModels = useMemo9(() => {
6213
6285
  if (!allModels?.length) return [];
6214
6286
  const userModels = userInfo?.models;
@@ -6503,6 +6575,8 @@ var init_LiteLLMPage = __esm({
6503
6575
  loading: teamsLoading,
6504
6576
  getTeamUsage: (teamId) => teamUsageCache[teamId] ?? null,
6505
6577
  getTeamUsageLoading: (teamId) => teamUsageLoading[teamId] ?? false,
6578
+ getTeamMemberUsage: (teamId) => memberUsageCache[teamId] ?? null,
6579
+ getTeamMemberUsageLoading: (teamId) => memberUsageLoading[teamId] ?? false,
6506
6580
  canManage: teamMgmtEnabled && canManageTeam && !readOnly,
6507
6581
  onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
6508
6582
  canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
@@ -6510,7 +6584,10 @@ var init_LiteLLMPage = __esm({
6510
6584
  canManageMembers: (t) => teamMgmtEnabled && canManageMembers && isTeamMemberManager(t, userInfo?.user_id, memberManagerRoles, readOnly),
6511
6585
  onManageMembers: (t) => setManageTeam({ mode: "members", team: t }),
6512
6586
  readOnly,
6513
- onTeamExpand: (team) => loadTeamUsage(team.team_id)
6587
+ onTeamExpand: (team) => {
6588
+ loadTeamUsage(team.team_id);
6589
+ if (liteLlmConfig?.teamUsage?.memberBreakdown) loadMemberUsage(team.team_id);
6590
+ }
6514
6591
  }
6515
6592
  );
6516
6593
  })(),
@@ -6666,6 +6743,131 @@ var init_LiteLLMPage = __esm({
6666
6743
  }
6667
6744
  });
6668
6745
 
6746
+ // src/connect.ts
6747
+ function isLoopbackCallback(uri) {
6748
+ if (!uri) return false;
6749
+ try {
6750
+ const url = new URL(uri);
6751
+ return url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1") && url.pathname === "/callback" && url.search === "" && url.hash === "";
6752
+ } catch {
6753
+ return false;
6754
+ }
6755
+ }
6756
+ function postToLoopback(redirectUri, fields) {
6757
+ const form = document.createElement("form");
6758
+ form.method = "POST";
6759
+ form.action = redirectUri;
6760
+ for (const [name, value] of fields) {
6761
+ const input = document.createElement("input");
6762
+ input.type = "hidden";
6763
+ input.name = name;
6764
+ input.value = value;
6765
+ form.appendChild(input);
6766
+ }
6767
+ document.body.appendChild(form);
6768
+ form.submit();
6769
+ }
6770
+ var init_connect = __esm({
6771
+ "src/connect.ts"() {
6772
+ "use strict";
6773
+ }
6774
+ });
6775
+
6776
+ // src/components/ConnectPage.tsx
6777
+ var ConnectPage_exports = {};
6778
+ __export(ConnectPage_exports, {
6779
+ ConnectPage: () => ConnectPage
6780
+ });
6781
+ import { useState as useState13 } from "react";
6782
+ import Alert7 from "@mui/material/Alert";
6783
+ import Box18 from "@mui/material/Box";
6784
+ import Button8 from "@mui/material/Button";
6785
+ import Checkbox3 from "@mui/material/Checkbox";
6786
+ import FormControlLabel3 from "@mui/material/FormControlLabel";
6787
+ import FormGroup from "@mui/material/FormGroup";
6788
+ import Paper9 from "@mui/material/Paper";
6789
+ import Typography16 from "@mui/material/Typography";
6790
+ import { useSearchParams as useSearchParams2 } from "react-router-dom";
6791
+ import { useAsync as useAsync3 } from "react-use";
6792
+ import { useApi as useApi5 } from "@backstage/core-plugin-api";
6793
+ import { Content as Content2, Progress as Progress2 } from "@backstage/core-components";
6794
+ import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
6795
+ var ConnectPage;
6796
+ var init_ConnectPage = __esm({
6797
+ "src/components/ConnectPage.tsx"() {
6798
+ "use strict";
6799
+ init_api();
6800
+ init_connect();
6801
+ ConnectPage = () => {
6802
+ const api = useApi5(liteLlmApiRef);
6803
+ const [params] = useSearchParams2();
6804
+ const redirectUri = params.get("redirect_uri");
6805
+ const state = params.get("state") ?? "";
6806
+ const client = params.get("client") || "a local application";
6807
+ const teams = useAsync3(() => api.getTeams(), [api]);
6808
+ const [selected, setSelected] = useState13();
6809
+ const [busy, setBusy] = useState13(false);
6810
+ const [error, setError] = useState13();
6811
+ if (!isLoopbackCallback(redirectUri)) {
6812
+ return /* @__PURE__ */ jsx19(Content2, { children: /* @__PURE__ */ jsx19(Alert7, { severity: "error", children: "Invalid connection link: redirect_uri must be http://localhost:<port>/callback." }) });
6813
+ }
6814
+ if (teams.loading) return /* @__PURE__ */ jsx19(Progress2, {});
6815
+ const all = teams.value ?? [];
6816
+ const chosen = selected ?? new Set(all.map((t) => t.team_id));
6817
+ const toggle = (id) => {
6818
+ const next = new Set(chosen);
6819
+ if (!next.delete(id)) next.add(id);
6820
+ setSelected(next);
6821
+ };
6822
+ const connect = async () => {
6823
+ setBusy(true);
6824
+ setError(void 0);
6825
+ try {
6826
+ const ids = all.length ? all.filter((t) => chosen.has(t.team_id)).map((t) => t.team_id) : [void 0];
6827
+ const keys = [];
6828
+ for (const id of ids) keys.push(["key", (await api.connectLocalClient(redirectUri, id)).key]);
6829
+ postToLoopback(redirectUri, [["state", state], ...keys]);
6830
+ } catch (e) {
6831
+ setError(e instanceof Error ? e.message : String(e));
6832
+ setBusy(false);
6833
+ }
6834
+ };
6835
+ return /* @__PURE__ */ jsx19(Content2, { children: /* @__PURE__ */ jsx19(Box18, { maxWidth: 520, mx: "auto", mt: 4, children: /* @__PURE__ */ jsxs18(Paper9, { sx: { p: 3 }, children: [
6836
+ /* @__PURE__ */ jsxs18(Typography16, { variant: "h5", gutterBottom: true, children: [
6837
+ "Connect ",
6838
+ client
6839
+ ] }),
6840
+ /* @__PURE__ */ jsxs18(Typography16, { variant: "body2", color: "text.secondary", paragraph: true, children: [
6841
+ client,
6842
+ " will receive an API key for each selected team. Connecting again replaces the keys created by a previous connection."
6843
+ ] }),
6844
+ teams.error && /* @__PURE__ */ jsxs18(Alert7, { severity: "error", children: [
6845
+ "Could not load your teams: ",
6846
+ teams.error.message
6847
+ ] }),
6848
+ all.length > 0 && /* @__PURE__ */ jsx19(FormGroup, { sx: { mb: 2 }, children: all.map((t) => /* @__PURE__ */ jsx19(
6849
+ FormControlLabel3,
6850
+ {
6851
+ control: /* @__PURE__ */ jsx19(Checkbox3, { checked: chosen.has(t.team_id), onChange: () => toggle(t.team_id) }),
6852
+ label: t.team_alias ?? t.team_id
6853
+ },
6854
+ t.team_id
6855
+ )) }),
6856
+ error && /* @__PURE__ */ jsx19(Alert7, { severity: "error", sx: { mb: 2 }, children: error }),
6857
+ /* @__PURE__ */ jsx19(
6858
+ Button8,
6859
+ {
6860
+ variant: "contained",
6861
+ onClick: connect,
6862
+ disabled: busy || !!teams.error || all.length > 0 && chosen.size === 0,
6863
+ children: busy ? "Connecting\u2026" : "Connect"
6864
+ }
6865
+ )
6866
+ ] }) }) });
6867
+ };
6868
+ }
6869
+ });
6870
+
6669
6871
  // src/plugin.tsx
6670
6872
  init_api();
6671
6873
  init_routes();
@@ -6677,7 +6879,7 @@ import {
6677
6879
  fetchApiRef,
6678
6880
  discoveryApiRef
6679
6881
  } from "@backstage/frontend-plugin-api";
6680
- import { jsx as jsx19 } from "react/jsx-runtime";
6882
+ import { jsx as jsx20 } from "react/jsx-runtime";
6681
6883
  var liteLlmApi = ApiBlueprint.make({
6682
6884
  params: (defineParams) => defineParams({
6683
6885
  api: liteLlmApiRef,
@@ -6689,11 +6891,21 @@ var liteLlmPage = PageBlueprint.make({
6689
6891
  params: {
6690
6892
  path: "/litellm",
6691
6893
  title: "LiteLLM",
6692
- icon: /* @__PURE__ */ jsx19(TrendingUpIcon, {}),
6894
+ icon: /* @__PURE__ */ jsx20(TrendingUpIcon, {}),
6693
6895
  routeRef: rootRouteRef,
6694
6896
  loader: async () => {
6695
6897
  const { LiteLLMPage: LiteLLMPage2 } = await Promise.resolve().then(() => (init_LiteLLMPage(), LiteLLMPage_exports));
6696
- return /* @__PURE__ */ jsx19(LiteLLMPage2, {});
6898
+ return /* @__PURE__ */ jsx20(LiteLLMPage2, {});
6899
+ }
6900
+ }
6901
+ });
6902
+ var liteLlmConnectPage = PageBlueprint.make({
6903
+ name: "connect",
6904
+ params: {
6905
+ path: "/litellm/connect",
6906
+ loader: async () => {
6907
+ const { ConnectPage: ConnectPage2 } = await Promise.resolve().then(() => (init_ConnectPage(), ConnectPage_exports));
6908
+ return /* @__PURE__ */ jsx20(ConnectPage2, {});
6697
6909
  }
6698
6910
  }
6699
6911
  });
@@ -6702,7 +6914,7 @@ var litellmPlugin = createFrontendPlugin({
6702
6914
  routes: {
6703
6915
  root: rootRouteRef
6704
6916
  },
6705
- extensions: [liteLlmApi, liteLlmPage]
6917
+ extensions: [liteLlmApi, liteLlmPage, liteLlmConnectPage]
6706
6918
  });
6707
6919
 
6708
6920
  // src/index.ts
@@ -6720,16 +6932,16 @@ init_format();
6720
6932
  init_dates();
6721
6933
  init_ui();
6722
6934
  init_widgetState();
6723
- import { useEffect as useEffect7, useMemo as useMemo10, useState as useState13 } from "react";
6724
- import Paper9 from "@mui/material/Paper";
6725
- import Box18 from "@mui/material/Box";
6726
- import Typography16 from "@mui/material/Typography";
6935
+ import { useEffect as useEffect7, useMemo as useMemo10, useState as useState14 } from "react";
6936
+ import Paper10 from "@mui/material/Paper";
6937
+ import Box19 from "@mui/material/Box";
6938
+ import Typography17 from "@mui/material/Typography";
6727
6939
  import FormControl2 from "@mui/material/FormControl";
6728
6940
  import Select2 from "@mui/material/Select";
6729
6941
  import MenuItem6 from "@mui/material/MenuItem";
6730
6942
  import Skeleton7 from "@mui/material/Skeleton";
6731
6943
  import { AreaChart as AreaChart3, Area as Area3, XAxis as XAxis3, Tooltip as Tooltip8, ResponsiveContainer as ResponsiveContainer3 } from "recharts";
6732
- import { useApi as useApi5 } from "@backstage/core-plugin-api";
6944
+ import { useApi as useApi6 } from "@backstage/core-plugin-api";
6733
6945
  import { useRouteRef as useRouteRef2 } from "@backstage/frontend-plugin-api";
6734
6946
  import { Link as Link3 } from "@backstage/core-components";
6735
6947
 
@@ -6776,7 +6988,7 @@ function usageSummary(usage) {
6776
6988
  }
6777
6989
 
6778
6990
  // src/components/LiteLLMHomeWidget.tsx
6779
- import { Fragment as Fragment10, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
6991
+ import { Fragment as Fragment10, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
6780
6992
  function presetToDateRange(preset) {
6781
6993
  const end = /* @__PURE__ */ new Date();
6782
6994
  const start = /* @__PURE__ */ new Date();
@@ -6794,13 +7006,13 @@ var LiteLLMHomeWidget = ({
6794
7006
  title = "LiteLLM Usage",
6795
7007
  bare = false
6796
7008
  }) => {
6797
- const api = useApi5(liteLlmApiRef);
7009
+ const api = useApi6(liteLlmApiRef);
6798
7010
  const moduleRouteRef = useRouteRef2(rootRouteRef);
6799
7011
  const { userInfo, keys, loading: profileLoading, error: profileError } = useLiteLLMProfile();
6800
- const [period, setPeriod] = useState13(defaultPeriod);
6801
- const [usageLoading, setUsageLoading] = useState13(true);
6802
- const [usageError, setUsageError] = useState13(null);
6803
- const [usage, setUsage] = useState13(null);
7012
+ const [period, setPeriod] = useState14(defaultPeriod);
7013
+ const [usageLoading, setUsageLoading] = useState14(true);
7014
+ const [usageError, setUsageError] = useState14(null);
7015
+ const [usage, setUsage] = useState14(null);
6804
7016
  useEffect7(() => {
6805
7017
  let cancelled = false;
6806
7018
  setUsageLoading(true);
@@ -6833,7 +7045,7 @@ var LiteLLMHomeWidget = ({
6833
7045
  }),
6834
7046
  [profileLoading, usageLoading, profileError, userInfo, usageError, keys]
6835
7047
  );
6836
- const Wrapper = bare ? Box18 : Paper9;
7048
+ const Wrapper = bare ? Box19 : Paper10;
6837
7049
  const partialFailure = !usageLoading && usageError && usage;
6838
7050
  const dailyData = (usage?.daily_usage ?? []).map((d) => ({
6839
7051
  date: d.date,
@@ -6845,10 +7057,10 @@ var LiteLLMHomeWidget = ({
6845
7057
  const endDate = toLocalDay(end);
6846
7058
  const dateRangeCaption = rangeCaption(startDate, endDate);
6847
7059
  const sparklineAriaLabelText = sparklineAriaLabel(dailyData);
6848
- return /* @__PURE__ */ jsxs18(Wrapper, { sx: bare ? { height: "100%" } : { p: 2, height: "100%" }, children: [
6849
- /* @__PURE__ */ jsxs18(Box18, { display: "flex", justifyContent: bare ? "flex-end" : "space-between", alignItems: "center", mb: 1.5, children: [
6850
- !bare && /* @__PURE__ */ jsx20(Typography16, { variant: "h6", children: title }),
6851
- /* @__PURE__ */ jsx20(FormControl2, { size: "small", sx: { minWidth: 90 }, children: /* @__PURE__ */ jsxs18(
7060
+ return /* @__PURE__ */ jsxs19(Wrapper, { sx: bare ? { height: "100%" } : { p: 2, height: "100%" }, children: [
7061
+ /* @__PURE__ */ jsxs19(Box19, { display: "flex", justifyContent: bare ? "flex-end" : "space-between", alignItems: "center", mb: 1.5, children: [
7062
+ !bare && /* @__PURE__ */ jsx21(Typography17, { variant: "h6", children: title }),
7063
+ /* @__PURE__ */ jsx21(FormControl2, { size: "small", sx: { minWidth: 90 }, children: /* @__PURE__ */ jsxs19(
6852
7064
  Select2,
6853
7065
  {
6854
7066
  value: period,
@@ -6856,23 +7068,23 @@ var LiteLLMHomeWidget = ({
6856
7068
  displayEmpty: true,
6857
7069
  inputProps: { "aria-label": "Usage period" },
6858
7070
  children: [
6859
- /* @__PURE__ */ jsx20(MenuItem6, { value: "today", children: "Today" }),
6860
- /* @__PURE__ */ jsx20(MenuItem6, { value: "7d", children: "7d" }),
6861
- /* @__PURE__ */ jsx20(MenuItem6, { value: "30d", children: "30d" })
7071
+ /* @__PURE__ */ jsx21(MenuItem6, { value: "today", children: "Today" }),
7072
+ /* @__PURE__ */ jsx21(MenuItem6, { value: "7d", children: "7d" }),
7073
+ /* @__PURE__ */ jsx21(MenuItem6, { value: "30d", children: "30d" })
6862
7074
  ]
6863
7075
  }
6864
7076
  ) })
6865
7077
  ] }),
6866
- viewState.kind === "loading" && /* @__PURE__ */ jsxs18(Box18, { sx: { minHeight: 120 }, children: [
6867
- /* @__PURE__ */ jsx20(Skeleton7, { variant: "text", width: "60%", height: 20, sx: { mb: 1 } }),
6868
- /* @__PURE__ */ jsx20(Skeleton7, { variant: "rectangular", width: "100%", height: 100 })
7078
+ viewState.kind === "loading" && /* @__PURE__ */ jsxs19(Box19, { sx: { minHeight: 120 }, children: [
7079
+ /* @__PURE__ */ jsx21(Skeleton7, { variant: "text", width: "60%", height: 20, sx: { mb: 1 } }),
7080
+ /* @__PURE__ */ jsx21(Skeleton7, { variant: "rectangular", width: "100%", height: 100 })
6869
7081
  ] }),
6870
- viewState.kind === "error" && /* @__PURE__ */ jsx20(Typography16, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: viewState.message }),
6871
- viewState.kind === "unprovisioned" && /* @__PURE__ */ jsx20(Typography16, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: UNPROVISIONED_MSG }),
6872
- viewState.kind === "ready" && partialFailure && /* @__PURE__ */ jsx20(Box18, { sx: { mt: 1, mb: 1, p: 1, backgroundColor: "action.hover", borderRadius: 1 }, children: /* @__PURE__ */ jsx20(Typography16, { variant: "body2", color: "text.secondary", children: USAGE_UNAVAILABLE_MSG }) }),
6873
- viewState.kind === "ready" && /* @__PURE__ */ jsxs18(Fragment10, { children: [
6874
- /* @__PURE__ */ jsx20(
6875
- Typography16,
7082
+ viewState.kind === "error" && /* @__PURE__ */ jsx21(Typography17, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: viewState.message }),
7083
+ viewState.kind === "unprovisioned" && /* @__PURE__ */ jsx21(Typography17, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: UNPROVISIONED_MSG }),
7084
+ viewState.kind === "ready" && partialFailure && /* @__PURE__ */ jsx21(Box19, { sx: { mt: 1, mb: 1, p: 1, backgroundColor: "action.hover", borderRadius: 1 }, children: /* @__PURE__ */ jsx21(Typography17, { variant: "body2", color: "text.secondary", children: USAGE_UNAVAILABLE_MSG }) }),
7085
+ viewState.kind === "ready" && /* @__PURE__ */ jsxs19(Fragment10, { children: [
7086
+ /* @__PURE__ */ jsx21(
7087
+ Typography17,
6876
7088
  {
6877
7089
  variant: "body2",
6878
7090
  sx: {
@@ -6883,18 +7095,18 @@ var LiteLLMHomeWidget = ({
6883
7095
  children: viewState.usageUnavailable ? USAGE_UNAVAILABLE_MSG : usageSummary(usage)
6884
7096
  }
6885
7097
  ),
6886
- hasSparkline && !viewState.usageUnavailable && /* @__PURE__ */ jsxs18(Fragment10, { children: [
6887
- /* @__PURE__ */ jsx20(
6888
- Box18,
7098
+ hasSparkline && !viewState.usageUnavailable && /* @__PURE__ */ jsxs19(Fragment10, { children: [
7099
+ /* @__PURE__ */ jsx21(
7100
+ Box19,
6889
7101
  {
6890
7102
  height: 80,
6891
7103
  role: "img",
6892
7104
  "aria-label": sparklineAriaLabelText,
6893
7105
  sx: { mb: 0.5 },
6894
- children: /* @__PURE__ */ jsx20(ResponsiveContainer3, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs18(AreaChart3, { data: dailyData, margin: { top: 4, right: 0, bottom: 0, left: 0 }, children: [
6895
- /* @__PURE__ */ jsx20(XAxis3, { dataKey: "date", hide: true }),
6896
- /* @__PURE__ */ jsx20(Tooltip8, { content: /* @__PURE__ */ jsx20(ChartTooltip, { valueFormatter: fmtUsd }) }),
6897
- /* @__PURE__ */ jsx20(
7106
+ children: /* @__PURE__ */ jsx21(ResponsiveContainer3, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs19(AreaChart3, { data: dailyData, margin: { top: 4, right: 0, bottom: 0, left: 0 }, children: [
7107
+ /* @__PURE__ */ jsx21(XAxis3, { dataKey: "date", hide: true }),
7108
+ /* @__PURE__ */ jsx21(Tooltip8, { content: /* @__PURE__ */ jsx21(ChartTooltip, { valueFormatter: fmtUsd }) }),
7109
+ /* @__PURE__ */ jsx21(
6898
7110
  Area3,
6899
7111
  {
6900
7112
  type: "monotone",
@@ -6910,13 +7122,13 @@ var LiteLLMHomeWidget = ({
6910
7122
  ] }) })
6911
7123
  }
6912
7124
  ),
6913
- /* @__PURE__ */ jsxs18(Typography16, { variant: "caption", color: "text.secondary", sx: { display: "block", mb: 1 }, children: [
7125
+ /* @__PURE__ */ jsxs19(Typography17, { variant: "caption", color: "text.secondary", sx: { display: "block", mb: 1 }, children: [
6914
7126
  "daily spend (",
6915
7127
  dateRangeCaption,
6916
7128
  ")"
6917
7129
  ] })
6918
7130
  ] }),
6919
- moduleRouteRef?.() && /* @__PURE__ */ jsx20(Typography16, { variant: "caption", sx: { mt: 1, display: "block" }, children: /* @__PURE__ */ jsx20(Link3, { to: moduleRouteRef(), color: "primary", children: "Open LiteLLM \u2192" }) })
7131
+ moduleRouteRef?.() && /* @__PURE__ */ jsx21(Typography17, { variant: "caption", sx: { mt: 1, display: "block" }, children: /* @__PURE__ */ jsx21(Link3, { to: moduleRouteRef(), color: "primary", children: "Open LiteLLM \u2192" }) })
6920
7132
  ] })
6921
7133
  ] });
6922
7134
  };
@@ -6929,19 +7141,19 @@ init_useLiteLLMProfile();
6929
7141
  init_api();
6930
7142
  init_format();
6931
7143
  init_dates();
6932
- import { useCallback as useCallback5, useEffect as useEffect8, useId as useId2, useMemo as useMemo11, useState as useState14 } from "react";
7144
+ import { useCallback as useCallback5, useEffect as useEffect8, useId as useId2, useMemo as useMemo11, useState as useState15 } from "react";
6933
7145
  import { useRouteRef as useRouteRef3 } from "@backstage/frontend-plugin-api";
6934
- import Paper10 from "@mui/material/Paper";
6935
- import Box19 from "@mui/material/Box";
6936
- import Button8 from "@mui/material/Button";
6937
- import Typography17 from "@mui/material/Typography";
7146
+ import Paper11 from "@mui/material/Paper";
7147
+ import Box20 from "@mui/material/Box";
7148
+ import Button9 from "@mui/material/Button";
7149
+ import Typography18 from "@mui/material/Typography";
6938
7150
  import Skeleton8 from "@mui/material/Skeleton";
6939
7151
  import Collapse4 from "@mui/material/Collapse";
6940
7152
  import { useTheme as useTheme4 } from "@mui/material/styles";
6941
7153
  import useMediaQuery from "@mui/material/useMediaQuery";
6942
7154
  import { ExpandMore as ExpandMore4 } from "@mui/icons-material";
6943
7155
  import { AreaChart as AreaChart4, Area as Area4, ResponsiveContainer as ResponsiveContainer4, Tooltip as Tooltip9, ReferenceLine as ReferenceLine2, XAxis as XAxis4 } from "recharts";
6944
- import { useApi as useApi6 } from "@backstage/core-plugin-api";
7156
+ import { useApi as useApi7 } from "@backstage/core-plugin-api";
6945
7157
  import { Link as Link4 } from "@backstage/core-components";
6946
7158
 
6947
7159
  // src/ctas.ts
@@ -6969,7 +7181,7 @@ init_GenerateKeyButton();
6969
7181
  init_BudgetLimitList();
6970
7182
  init_budget();
6971
7183
  init_routes();
6972
- import { Fragment as Fragment11, jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
7184
+ import { Fragment as Fragment11, jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
6973
7185
  var LEVEL = {
6974
7186
  key: { name: "Key", none: "No cap (unlimited)" },
6975
7187
  user: { name: "User", none: "No personal budget" },
@@ -6993,8 +7205,8 @@ function resetLabel(limit) {
6993
7205
  const window2 = fmtBudgetDuration(limit.budgetDuration);
6994
7206
  return window2 ? `resets ${window2}` : "never resets";
6995
7207
  }
6996
- var Tag = ({ children, tone, title }) => /* @__PURE__ */ jsx21(
6997
- Typography17,
7208
+ var Tag = ({ children, tone, title }) => /* @__PURE__ */ jsx22(
7209
+ Typography18,
6998
7210
  {
6999
7211
  title,
7000
7212
  sx: (theme) => ({
@@ -7011,10 +7223,10 @@ var Tag = ({ children, tone, title }) => /* @__PURE__ */ jsx21(
7011
7223
  children
7012
7224
  }
7013
7225
  );
7014
- var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE__ */ jsxs19(Box19, { sx: { minWidth: 0, flex: 1 }, children: [
7015
- /* @__PURE__ */ jsxs19(Box19, { sx: { display: "flex", alignItems: "center", gap: 0.625, minWidth: 0 }, children: [
7016
- /* @__PURE__ */ jsx21(
7017
- Box19,
7226
+ var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE__ */ jsxs20(Box20, { sx: { minWidth: 0, flex: 1 }, children: [
7227
+ /* @__PURE__ */ jsxs20(Box20, { sx: { display: "flex", alignItems: "center", gap: 0.625, minWidth: 0 }, children: [
7228
+ /* @__PURE__ */ jsx22(
7229
+ Box20,
7018
7230
  {
7019
7231
  sx: (theme) => ({
7020
7232
  width: 6,
@@ -7025,10 +7237,10 @@ var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE_
7025
7237
  })
7026
7238
  }
7027
7239
  ),
7028
- /* @__PURE__ */ jsx21(Tag, { children: label })
7240
+ /* @__PURE__ */ jsx22(Tag, { children: label })
7029
7241
  ] }),
7030
- /* @__PURE__ */ jsx21(
7031
- Typography17,
7242
+ /* @__PURE__ */ jsx22(
7243
+ Typography18,
7032
7244
  {
7033
7245
  title,
7034
7246
  sx: {
@@ -7044,8 +7256,8 @@ var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE_
7044
7256
  children: value
7045
7257
  }
7046
7258
  ),
7047
- /* @__PURE__ */ jsx21(
7048
- Typography17,
7259
+ /* @__PURE__ */ jsx22(
7260
+ Typography18,
7049
7261
  {
7050
7262
  variant: "caption",
7051
7263
  color: "text.secondary",
@@ -7075,8 +7287,8 @@ var LevelRow = ({
7075
7287
  const subNote = () => {
7076
7288
  if (overCap) return "Over cap";
7077
7289
  if (extra > 0 && keysHref) {
7078
- return /* @__PURE__ */ jsxs19(
7079
- Typography17,
7290
+ return /* @__PURE__ */ jsxs20(
7291
+ Typography18,
7080
7292
  {
7081
7293
  component: Link4,
7082
7294
  to: keysHref,
@@ -7098,8 +7310,8 @@ var LevelRow = ({
7098
7310
  return limit?.sublabel ?? null;
7099
7311
  };
7100
7312
  const gaugeAriaLabel = limit ? `${name} budget used: ${Math.round(limit.pct)}%` : `${name} \u2014 no cap`;
7101
- return /* @__PURE__ */ jsxs19(
7102
- Box19,
7313
+ return /* @__PURE__ */ jsxs20(
7314
+ Box20,
7103
7315
  {
7104
7316
  sx: {
7105
7317
  display: "grid",
@@ -7110,7 +7322,7 @@ var LevelRow = ({
7110
7322
  minWidth: 0
7111
7323
  },
7112
7324
  children: [
7113
- /* @__PURE__ */ jsx21(
7325
+ /* @__PURE__ */ jsx22(
7114
7326
  Gauge,
7115
7327
  {
7116
7328
  value: limit?.pct ?? 0,
@@ -7120,11 +7332,11 @@ var LevelRow = ({
7120
7332
  ariaLabel: gaugeAriaLabel
7121
7333
  }
7122
7334
  ),
7123
- /* @__PURE__ */ jsxs19(Box19, { sx: { minWidth: 0 }, children: [
7124
- /* @__PURE__ */ jsx21(Tag, { tone: tone === "warning" || tone === "danger" ? tone : void 0, children: name }),
7125
- limit ? /* @__PURE__ */ jsxs19(Fragment11, { children: [
7126
- /* @__PURE__ */ jsx21(
7127
- Typography17,
7335
+ /* @__PURE__ */ jsxs20(Box20, { sx: { minWidth: 0 }, children: [
7336
+ /* @__PURE__ */ jsx22(Tag, { tone: tone === "warning" || tone === "danger" ? tone : void 0, children: name }),
7337
+ limit ? /* @__PURE__ */ jsxs20(Fragment11, { children: [
7338
+ /* @__PURE__ */ jsx22(
7339
+ Typography18,
7128
7340
  {
7129
7341
  variant: "caption",
7130
7342
  title: limit.sublabel ? `${limit.label} \xB7 ${limit.sublabel}` : limit.label,
@@ -7140,8 +7352,8 @@ var LevelRow = ({
7140
7352
  children: limit.label
7141
7353
  }
7142
7354
  ),
7143
- /* @__PURE__ */ jsx21(
7144
- Typography17,
7355
+ /* @__PURE__ */ jsx22(
7356
+ Typography18,
7145
7357
  {
7146
7358
  variant: "caption",
7147
7359
  color: overCap ? "error" : "text.secondary",
@@ -7157,8 +7369,8 @@ var LevelRow = ({
7157
7369
  children: subNote()
7158
7370
  }
7159
7371
  )
7160
- ] }) : /* @__PURE__ */ jsx21(
7161
- Typography17,
7372
+ ] }) : /* @__PURE__ */ jsx22(
7373
+ Typography18,
7162
7374
  {
7163
7375
  variant: "caption",
7164
7376
  color: "text.secondary",
@@ -7174,9 +7386,9 @@ var LevelRow = ({
7174
7386
  }
7175
7387
  )
7176
7388
  ] }),
7177
- /* @__PURE__ */ jsxs19(Box19, { sx: { minWidth: 0, textAlign: "right" }, children: [
7178
- /* @__PURE__ */ jsx21(
7179
- Typography17,
7389
+ /* @__PURE__ */ jsxs20(Box20, { sx: { minWidth: 0, textAlign: "right" }, children: [
7390
+ /* @__PURE__ */ jsx22(
7391
+ Typography18,
7180
7392
  {
7181
7393
  title: limit ? `${fmtUsd(limit.spend)} of ${fmtUsd(limit.budget)}` : void 0,
7182
7394
  sx: {
@@ -7193,8 +7405,8 @@ var LevelRow = ({
7193
7405
  children: amountCaption(limit)
7194
7406
  }
7195
7407
  ),
7196
- /* @__PURE__ */ jsx21(
7197
- Typography17,
7408
+ /* @__PURE__ */ jsx22(
7409
+ Typography18,
7198
7410
  {
7199
7411
  variant: "caption",
7200
7412
  color: "text.secondary",
@@ -7225,11 +7437,11 @@ function amountNote(limit) {
7225
7437
  var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, maxBudget }) => {
7226
7438
  const renderPlot = () => {
7227
7439
  if (loading) {
7228
- return /* @__PURE__ */ jsx21(Skeleton8, { variant: "rectangular", width: "100%", height: "100%" });
7440
+ return /* @__PURE__ */ jsx22(Skeleton8, { variant: "rectangular", width: "100%", height: "100%" });
7229
7441
  }
7230
7442
  if (data.length === 0) {
7231
- return /* @__PURE__ */ jsx21(
7232
- Box19,
7443
+ return /* @__PURE__ */ jsx22(
7444
+ Box20,
7233
7445
  {
7234
7446
  display: "flex",
7235
7447
  justifyContent: "center",
@@ -7240,10 +7452,10 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
7240
7452
  }
7241
7453
  );
7242
7454
  }
7243
- return /* @__PURE__ */ jsx21(ResponsiveContainer4, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs19(AreaChart4, { data, margin: { top: 4, right: 0, bottom: 0, left: 0 }, children: [
7244
- /* @__PURE__ */ jsx21(XAxis4, { dataKey: "date", hide: true }),
7245
- /* @__PURE__ */ jsx21(Tooltip9, { content: /* @__PURE__ */ jsx21(ChartTooltip, { valueFormatter: fmtUsd }) }),
7246
- maxBudget !== void 0 && /* @__PURE__ */ jsx21(
7455
+ return /* @__PURE__ */ jsx22(ResponsiveContainer4, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs20(AreaChart4, { data, margin: { top: 4, right: 0, bottom: 0, left: 0 }, children: [
7456
+ /* @__PURE__ */ jsx22(XAxis4, { dataKey: "date", hide: true }),
7457
+ /* @__PURE__ */ jsx22(Tooltip9, { content: /* @__PURE__ */ jsx22(ChartTooltip, { valueFormatter: fmtUsd }) }),
7458
+ maxBudget !== void 0 && /* @__PURE__ */ jsx22(
7247
7459
  ReferenceLine2,
7248
7460
  {
7249
7461
  y: maxBudget,
@@ -7252,7 +7464,7 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
7252
7464
  strokeWidth: 1
7253
7465
  }
7254
7466
  ),
7255
- /* @__PURE__ */ jsx21(
7467
+ /* @__PURE__ */ jsx22(
7256
7468
  Area4,
7257
7469
  {
7258
7470
  type: "monotone",
@@ -7274,10 +7486,10 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
7274
7486
  if (data.length === 0) return "No spend this month";
7275
7487
  return mtdCaption();
7276
7488
  })();
7277
- return /* @__PURE__ */ jsxs19(Box19, { role: "img", "aria-label": sparklineAriaLabel(data), sx: { minWidth: 0 }, children: [
7278
- /* @__PURE__ */ jsx21(Box19, { sx: { height, width: "100%" }, children: renderPlot() }),
7279
- /* @__PURE__ */ jsxs19(
7280
- Box19,
7489
+ return /* @__PURE__ */ jsxs20(Box20, { role: "img", "aria-label": sparklineAriaLabel(data), sx: { minWidth: 0 }, children: [
7490
+ /* @__PURE__ */ jsx22(Box20, { sx: { height, width: "100%" }, children: renderPlot() }),
7491
+ /* @__PURE__ */ jsxs20(
7492
+ Box20,
7281
7493
  {
7282
7494
  sx: {
7283
7495
  display: "flex",
@@ -7288,10 +7500,10 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
7288
7500
  minWidth: 0
7289
7501
  },
7290
7502
  children: [
7291
- /* @__PURE__ */ jsxs19(Box19, { sx: { display: "flex", alignItems: "baseline", gap: 0.75, minWidth: 0 }, children: [
7292
- /* @__PURE__ */ jsx21(Tag, { children: "Spent (mtd)" }),
7293
- /* @__PURE__ */ jsx21(
7294
- Typography17,
7503
+ /* @__PURE__ */ jsxs20(Box20, { sx: { display: "flex", alignItems: "baseline", gap: 0.75, minWidth: 0 }, children: [
7504
+ /* @__PURE__ */ jsx22(Tag, { children: "Spent (mtd)" }),
7505
+ /* @__PURE__ */ jsx22(
7506
+ Typography18,
7295
7507
  {
7296
7508
  variant: "caption",
7297
7509
  color: "text.secondary",
@@ -7300,8 +7512,8 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
7300
7512
  }
7301
7513
  )
7302
7514
  ] }),
7303
- /* @__PURE__ */ jsx21(
7304
- Typography17,
7515
+ /* @__PURE__ */ jsx22(
7516
+ Typography18,
7305
7517
  {
7306
7518
  title: loading || usageUnavailable ? void 0 : `${fmtUsd(mtdSpend)} spent month to date`,
7307
7519
  sx: {
@@ -7345,7 +7557,7 @@ var LiteLLMBudgetGauges = ({
7345
7557
  teams: propTeams,
7346
7558
  keys: propKeys
7347
7559
  }) => {
7348
- const api = useApi6(liteLlmApiRef);
7560
+ const api = useApi7(liteLlmApiRef);
7349
7561
  const theme = useTheme4();
7350
7562
  const isSmallScreen = useMediaQuery(theme.breakpoints.down("sm"));
7351
7563
  const gaugeSize = isSmallScreen ? Math.min(48, size) : size;
@@ -7353,17 +7565,17 @@ var LiteLLMBudgetGauges = ({
7353
7565
  const moduleRouteRef = useRouteRef3(rootRouteRef);
7354
7566
  const moduleHref = propModuleHref ?? moduleRouteRef?.();
7355
7567
  const { userInfo: hookUserInfo, teams: hookTeams, keys: hookKeys, loading: profileLoading, error: profileError } = useLiteLLMProfile();
7356
- const [usageLoading, setUsageLoading] = useState14(true);
7357
- const [usageError, setUsageError] = useState14(null);
7358
- const [dailySpend, setDailySpend] = useState14([]);
7359
- const [mtdSpend, setMtdSpend] = useState14(0);
7568
+ const [usageLoading, setUsageLoading] = useState15(true);
7569
+ const [usageError, setUsageError] = useState15(null);
7570
+ const [dailySpend, setDailySpend] = useState15([]);
7571
+ const [mtdSpend, setMtdSpend] = useState15(0);
7360
7572
  const user = propUserInfo !== void 0 ? propUserInfo : hookUserInfo;
7361
7573
  const teams = propTeams !== void 0 ? propTeams : hookTeams;
7362
7574
  const keys = propKeys !== void 0 ? propKeys : hookKeys;
7363
7575
  const loading = propUserInfo === void 0 ? profileLoading : usageLoading;
7364
7576
  const error = propUserInfo === void 0 ? profileError : usageError;
7365
7577
  const isControlled = expanded !== void 0;
7366
- const [uncontrolledExpanded, setUncontrolledExpanded] = useState14(defaultExpanded);
7578
+ const [uncontrolledExpanded, setUncontrolledExpanded] = useState15(defaultExpanded);
7367
7579
  const isExpanded = isControlled ? expanded : uncontrolledExpanded;
7368
7580
  const toggleExpanded = useCallback5(() => {
7369
7581
  const next = !isExpanded;
@@ -7444,20 +7656,20 @@ var LiteLLMBudgetGauges = ({
7444
7656
  switch (cta.kind) {
7445
7657
  case "new-key":
7446
7658
  if (!onCreateKey && !moduleHref) return null;
7447
- return onCreateKey ? /* @__PURE__ */ jsx21(GenerateKeyButton, { size: "small", label, onClick: onCreateKey }, key) : /* @__PURE__ */ jsx21(GenerateKeyButton, { size: "small", label, to: `${moduleHref}?generate=1` }, key);
7659
+ return onCreateKey ? /* @__PURE__ */ jsx22(GenerateKeyButton, { size: "small", label, onClick: onCreateKey }, key) : /* @__PURE__ */ jsx22(GenerateKeyButton, { size: "small", label, to: `${moduleHref}?generate=1` }, key);
7448
7660
  case "module":
7449
7661
  if (!moduleHref) return null;
7450
- return /* @__PURE__ */ jsx21(Button8, { size: "small", variant: "text", component: Link4, to: moduleHref, children: label }, key);
7662
+ return /* @__PURE__ */ jsx22(Button9, { size: "small", variant: "text", component: Link4, to: moduleHref, children: label }, key);
7451
7663
  case "all-limits":
7452
- return /* @__PURE__ */ jsx21(
7453
- Button8,
7664
+ return /* @__PURE__ */ jsx22(
7665
+ Button9,
7454
7666
  {
7455
7667
  size: "small",
7456
7668
  variant: "text",
7457
7669
  onClick: toggleExpanded,
7458
7670
  "aria-expanded": isExpanded,
7459
7671
  "aria-controls": expandedRegionId,
7460
- endIcon: /* @__PURE__ */ jsx21(
7672
+ endIcon: /* @__PURE__ */ jsx22(
7461
7673
  ExpandMore4,
7462
7674
  {
7463
7675
  sx: (muiTheme) => ({
@@ -7476,11 +7688,11 @@ var LiteLLMBudgetGauges = ({
7476
7688
  }
7477
7689
  };
7478
7690
  const hasFooter = resolvedCtas.length > 0 || !!action;
7479
- const Wrapper = bare ? Box19 : Paper10;
7480
- return /* @__PURE__ */ jsxs19(Wrapper, { sx: bare ? { height: "100%" } : { p: 2, height: "100%" }, children: [
7481
- /* @__PURE__ */ jsxs19(Box19, { sx: { display: "flex", alignItems: "center", gap: 1, mb: 1.5, minWidth: 0, justifyContent: bare ? "flex-end" : void 0 }, children: [
7482
- !bare && /* @__PURE__ */ jsx21(Typography17, { variant: "h6", lineHeight: 1.2, sx: { minWidth: 0, flex: 1 }, children: title }),
7483
- !loading && !error && /* @__PURE__ */ jsx21(
7691
+ const Wrapper = bare ? Box20 : Paper11;
7692
+ return /* @__PURE__ */ jsxs20(Wrapper, { sx: bare ? { height: "100%" } : { p: 2, height: "100%" }, children: [
7693
+ /* @__PURE__ */ jsxs20(Box20, { sx: { display: "flex", alignItems: "center", gap: 1, mb: 1.5, minWidth: 0, justifyContent: bare ? "flex-end" : void 0 }, children: [
7694
+ !bare && /* @__PURE__ */ jsx22(Typography18, { variant: "h6", lineHeight: 1.2, sx: { minWidth: 0, flex: 1 }, children: title }),
7695
+ !loading && !error && /* @__PURE__ */ jsx22(
7484
7696
  StatusPill,
7485
7697
  {
7486
7698
  label: summaryText,
@@ -7489,19 +7701,19 @@ var LiteLLMBudgetGauges = ({
7489
7701
  }
7490
7702
  )
7491
7703
  ] }),
7492
- viewState.kind === "loading" && /* @__PURE__ */ jsx21(Box19, { sx: { display: "flex", flexDirection: "column", gap: 1.25, minHeight: size }, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsxs19(Box19, { sx: { display: "flex", alignItems: "center", gap: 1.25 }, children: [
7493
- /* @__PURE__ */ jsx21(Skeleton8, { variant: "circular", width: size, height: size }),
7494
- /* @__PURE__ */ jsxs19(Box19, { sx: { flex: 1 }, children: [
7495
- /* @__PURE__ */ jsx21(Skeleton8, { variant: "text", width: "70%", height: 12, sx: { mb: 0.25 } }),
7496
- /* @__PURE__ */ jsx21(Skeleton8, { variant: "text", width: "45%", height: 11 })
7704
+ viewState.kind === "loading" && /* @__PURE__ */ jsx22(Box20, { sx: { display: "flex", flexDirection: "column", gap: 1.25, minHeight: size }, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsxs20(Box20, { sx: { display: "flex", alignItems: "center", gap: 1.25 }, children: [
7705
+ /* @__PURE__ */ jsx22(Skeleton8, { variant: "circular", width: size, height: size }),
7706
+ /* @__PURE__ */ jsxs20(Box20, { sx: { flex: 1 }, children: [
7707
+ /* @__PURE__ */ jsx22(Skeleton8, { variant: "text", width: "70%", height: 12, sx: { mb: 0.25 } }),
7708
+ /* @__PURE__ */ jsx22(Skeleton8, { variant: "text", width: "45%", height: 11 })
7497
7709
  ] }),
7498
- /* @__PURE__ */ jsx21(Skeleton8, { variant: "text", width: 64, height: 12 })
7710
+ /* @__PURE__ */ jsx22(Skeleton8, { variant: "text", width: 64, height: 12 })
7499
7711
  ] }, i)) }),
7500
- viewState.kind === "error" && /* @__PURE__ */ jsx21(Typography17, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: viewState.message }),
7501
- viewState.kind === "unprovisioned" && /* @__PURE__ */ jsx21(Typography17, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: UNPROVISIONED_MSG }),
7502
- viewState.kind === "ready" && /* @__PURE__ */ jsxs19(Fragment11, { children: [
7503
- /* @__PURE__ */ jsxs19(
7504
- Box19,
7712
+ viewState.kind === "error" && /* @__PURE__ */ jsx22(Typography18, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: viewState.message }),
7713
+ viewState.kind === "unprovisioned" && /* @__PURE__ */ jsx22(Typography18, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: UNPROVISIONED_MSG }),
7714
+ viewState.kind === "ready" && /* @__PURE__ */ jsxs20(Fragment11, { children: [
7715
+ /* @__PURE__ */ jsxs20(
7716
+ Box20,
7505
7717
  {
7506
7718
  sx: {
7507
7719
  display: "flex",
@@ -7511,7 +7723,7 @@ var LiteLLMBudgetGauges = ({
7511
7723
  minWidth: 0
7512
7724
  },
7513
7725
  children: [
7514
- /* @__PURE__ */ jsx21(
7726
+ /* @__PURE__ */ jsx22(
7515
7727
  InlineStat,
7516
7728
  {
7517
7729
  label: "Today spent",
@@ -7521,8 +7733,8 @@ var LiteLLMBudgetGauges = ({
7521
7733
  title: usageLoading || viewState.usageUnavailable ? void 0 : "Spend since local midnight"
7522
7734
  }
7523
7735
  ),
7524
- /* @__PURE__ */ jsx21(Box19, { sx: { width: "1px", bgcolor: "divider", flexShrink: 0 } }),
7525
- /* @__PURE__ */ jsx21(
7736
+ /* @__PURE__ */ jsx22(Box20, { sx: { width: "1px", bgcolor: "divider", flexShrink: 0 } }),
7737
+ /* @__PURE__ */ jsx22(
7526
7738
  InlineStat,
7527
7739
  {
7528
7740
  label: "Month to date",
@@ -7534,15 +7746,15 @@ var LiteLLMBudgetGauges = ({
7534
7746
  ]
7535
7747
  }
7536
7748
  ),
7537
- /* @__PURE__ */ jsx21(Box19, { sx: { borderTop: "1px solid", borderColor: "divider" }, children: gauges.map((gauge, i) => /* @__PURE__ */ jsx21(
7538
- Box19,
7749
+ /* @__PURE__ */ jsx22(Box20, { sx: { borderTop: "1px solid", borderColor: "divider" }, children: gauges.map((gauge, i) => /* @__PURE__ */ jsx22(
7750
+ Box20,
7539
7751
  {
7540
7752
  sx: i === 0 ? void 0 : { borderTop: "1px solid", borderColor: "divider" },
7541
- children: /* @__PURE__ */ jsx21(LevelRow, { gauge, size: gaugeSize, keysHref: keysTabHref })
7753
+ children: /* @__PURE__ */ jsx22(LevelRow, { gauge, size: gaugeSize, keysHref: keysTabHref })
7542
7754
  },
7543
7755
  gauge.kind
7544
7756
  )) }),
7545
- /* @__PURE__ */ jsx21(Box19, { sx: { mt: 1.25 }, children: /* @__PURE__ */ jsx21(
7757
+ /* @__PURE__ */ jsx22(Box20, { sx: { mt: 1.25 }, children: /* @__PURE__ */ jsx22(
7546
7758
  SpendStrip,
7547
7759
  {
7548
7760
  data: dailySpend,
@@ -7553,8 +7765,8 @@ var LiteLLMBudgetGauges = ({
7553
7765
  maxBudget: user?.max_budget ?? void 0
7554
7766
  }
7555
7767
  ) }),
7556
- /* @__PURE__ */ jsx21(Collapse4, { in: isExpanded, unmountOnExit: true, children: /* @__PURE__ */ jsx21(
7557
- Box19,
7768
+ /* @__PURE__ */ jsx22(Collapse4, { in: isExpanded, unmountOnExit: true, children: /* @__PURE__ */ jsx22(
7769
+ Box20,
7558
7770
  {
7559
7771
  id: expandedRegionId,
7560
7772
  sx: {
@@ -7564,7 +7776,7 @@ var LiteLLMBudgetGauges = ({
7564
7776
  maxHeight: 300,
7565
7777
  overflowY: "auto"
7566
7778
  },
7567
- children: /* @__PURE__ */ jsx21(LimitListPanel, { children: /* @__PURE__ */ jsx21(
7779
+ children: /* @__PURE__ */ jsx22(LimitListPanel, { children: /* @__PURE__ */ jsx22(
7568
7780
  BudgetLimitList,
7569
7781
  {
7570
7782
  limits: expandedLimits,
@@ -7575,8 +7787,8 @@ var LiteLLMBudgetGauges = ({
7575
7787
  }
7576
7788
  ) })
7577
7789
  ] }),
7578
- hasFooter && /* @__PURE__ */ jsxs19(
7579
- Box19,
7790
+ hasFooter && /* @__PURE__ */ jsxs20(
7791
+ Box20,
7580
7792
  {
7581
7793
  sx: (muiTheme) => ({
7582
7794
  mt: 2,