@acarmisc/backstage-plugin-litellm 0.16.0 → 0.17.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.cjs.js CHANGED
@@ -1942,7 +1942,7 @@ var init_GenerateKeyDialog = __esm({
1942
1942
  });
1943
1943
 
1944
1944
  // src/components/ManageTeamDialog.tsx
1945
- var import_react5, import_Dialog3, import_DialogTitle3, import_DialogContent3, import_DialogActions3, import_TextField3, import_Button4, import_Alert2, import_Checkbox2, import_FormControlLabel2, import_Autocomplete3, import_Box5, import_Divider2, import_Typography5, import_IconButton3, import_List, import_ListItem, import_ListItemText, import_icons_material4, ManageTeamDialog;
1945
+ var import_react5, import_Dialog3, import_DialogTitle3, import_DialogContent3, import_DialogActions3, import_TextField3, import_Button4, import_Alert2, import_Checkbox2, import_FormControlLabel2, import_Autocomplete3, import_MenuItem2, import_Box5, import_Divider2, import_Typography5, import_IconButton3, import_List, import_ListItem, import_ListItemText, import_icons_material4, BUDGET_DURATION_OPTIONS, DEFAULT_BUDGET_DURATION, FALLBACK_BUDGET_CEILING, ManageTeamDialog;
1946
1946
  var init_ManageTeamDialog = __esm({
1947
1947
  "src/components/ManageTeamDialog.tsx"() {
1948
1948
  "use strict";
@@ -1957,6 +1957,7 @@ var init_ManageTeamDialog = __esm({
1957
1957
  import_Checkbox2 = __toESM(require("@mui/material/Checkbox"));
1958
1958
  import_FormControlLabel2 = __toESM(require("@mui/material/FormControlLabel"));
1959
1959
  import_Autocomplete3 = __toESM(require("@mui/material/Autocomplete"));
1960
+ import_MenuItem2 = __toESM(require("@mui/material/MenuItem"));
1960
1961
  import_Box5 = __toESM(require("@mui/material/Box"));
1961
1962
  import_Divider2 = __toESM(require("@mui/material/Divider"));
1962
1963
  import_Typography5 = __toESM(require("@mui/material/Typography"));
@@ -1965,6 +1966,15 @@ var init_ManageTeamDialog = __esm({
1965
1966
  import_ListItem = __toESM(require("@mui/material/ListItem"));
1966
1967
  import_ListItemText = __toESM(require("@mui/material/ListItemText"));
1967
1968
  import_icons_material4 = require("@mui/icons-material");
1969
+ BUDGET_DURATION_OPTIONS = [
1970
+ { value: "1d", label: "Daily (1d)" },
1971
+ { value: "7d", label: "Weekly (7d)" },
1972
+ { value: "30d", label: "Monthly (30d)" },
1973
+ { value: "90d", label: "Quarterly (90d)" },
1974
+ { value: "365d", label: "Yearly (365d)" }
1975
+ ];
1976
+ DEFAULT_BUDGET_DURATION = "30d";
1977
+ FALLBACK_BUDGET_CEILING = 1e3;
1968
1978
  ManageTeamDialog = ({
1969
1979
  open,
1970
1980
  onClose,
@@ -2001,21 +2011,23 @@ var init_ManageTeamDialog = __esm({
2001
2011
  const [mcpBusy, setMcpBusy] = (0, import_react5.useState)(false);
2002
2012
  const [mcpError, setMcpError] = (0, import_react5.useState)(null);
2003
2013
  const allowUnlimitedBudget = config?.teamManagement?.allowUnlimitedBudget ?? false;
2004
- const maxBudgetCeiling = config?.teamManagement?.maxBudgetCeiling;
2014
+ const maxBudgetCeiling = config?.teamManagement?.maxBudgetCeiling ?? FALLBACK_BUDGET_CEILING;
2005
2015
  (0, import_react5.useEffect)(() => {
2006
2016
  if (open) {
2007
2017
  if (mode === "edit" && team) {
2008
2018
  setAlias(team.team_alias ?? "");
2009
2019
  setModels(team.models ?? []);
2010
- setMaxBudget(team.max_budget ? String(team.max_budget) : "");
2020
+ setMaxBudget(
2021
+ team.max_budget ? String(team.max_budget) : String(maxBudgetCeiling)
2022
+ );
2011
2023
  setUnlimited(allowUnlimitedBudget && !team.max_budget);
2012
- setBudgetDuration("");
2024
+ setBudgetDuration(team.budget_duration ?? DEFAULT_BUDGET_DURATION);
2013
2025
  } else {
2014
2026
  setAlias("");
2015
2027
  setModels([]);
2016
- setMaxBudget("");
2028
+ setMaxBudget(String(maxBudgetCeiling));
2017
2029
  setUnlimited(allowUnlimitedBudget);
2018
- setBudgetDuration("");
2030
+ setBudgetDuration(DEFAULT_BUDGET_DURATION);
2019
2031
  }
2020
2032
  setError(null);
2021
2033
  setMemberRef("");
@@ -2026,7 +2038,7 @@ var init_ManageTeamDialog = __esm({
2026
2038
  setMcpIds(team?.object_permission?.mcp_servers ?? []);
2027
2039
  setMcpError(null);
2028
2040
  }
2029
- }, [open, mode, team, allowUnlimitedBudget]);
2041
+ }, [open, mode, team, allowUnlimitedBudget, maxBudgetCeiling]);
2030
2042
  const handleSubmit = async () => {
2031
2043
  setError(null);
2032
2044
  if (!alias.trim()) {
@@ -2047,7 +2059,7 @@ var init_ManageTeamDialog = __esm({
2047
2059
  setError("Budget must be a positive number");
2048
2060
  return;
2049
2061
  }
2050
- if (maxBudgetCeiling !== null && maxBudgetCeiling !== void 0 && budget > maxBudgetCeiling) {
2062
+ if (budget > maxBudgetCeiling) {
2051
2063
  setError(`Budget cannot exceed $${maxBudgetCeiling}`);
2052
2064
  return;
2053
2065
  }
@@ -2134,6 +2146,7 @@ var init_ManageTeamDialog = __esm({
2134
2146
  }
2135
2147
  };
2136
2148
  const modelNames = allModels.map((m) => m.model_name);
2149
+ const durationOptions = BUDGET_DURATION_OPTIONS.some((o) => o.value === budgetDuration) ? BUDGET_DURATION_OPTIONS : [...BUDGET_DURATION_OPTIONS, { value: budgetDuration, label: budgetDuration }];
2137
2150
  const members = team?.members_with_roles ?? [];
2138
2151
  const showMembers = mode === "edit" && !!canManageMembers;
2139
2152
  const showKnowledgeBases = mode === "edit" && !!canManageKnowledgeBases;
@@ -2169,7 +2182,8 @@ var init_ManageTeamDialog = __esm({
2169
2182
  value: maxBudget,
2170
2183
  onChange: (e) => setMaxBudget(e.target.value),
2171
2184
  disabled: submitting || unlimited,
2172
- helperText: maxBudgetCeiling !== null && maxBudgetCeiling !== void 0 ? `Maximum: $${maxBudgetCeiling}` : void 0,
2185
+ inputProps: { min: 0, max: maxBudgetCeiling },
2186
+ helperText: `Maximum: $${maxBudgetCeiling}`,
2173
2187
  fullWidth: true
2174
2188
  }
2175
2189
  ), allowUnlimitedBudget && /* @__PURE__ */ import_react5.default.createElement(
@@ -2181,13 +2195,15 @@ var init_ManageTeamDialog = __esm({
2181
2195
  ), /* @__PURE__ */ import_react5.default.createElement(
2182
2196
  import_TextField3.default,
2183
2197
  {
2198
+ select: true,
2184
2199
  label: "Budget Duration",
2185
2200
  value: budgetDuration,
2186
2201
  onChange: (e) => setBudgetDuration(e.target.value),
2187
- placeholder: "30d",
2188
- disabled: submitting,
2202
+ disabled: submitting || unlimited,
2203
+ helperText: "Spend-reset period for the team budget",
2189
2204
  fullWidth: true
2190
- }
2205
+ },
2206
+ durationOptions.map((o) => /* @__PURE__ */ import_react5.default.createElement(import_MenuItem2.default, { key: o.value, value: o.value }, o.label))
2191
2207
  ), showMembers && /* @__PURE__ */ import_react5.default.createElement(import_Box5.default, null, /* @__PURE__ */ import_react5.default.createElement(import_Divider2.default, { sx: { my: 1 } }), /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "subtitle2", sx: { mb: 1 } }, "Members"), memberError && /* @__PURE__ */ import_react5.default.createElement(import_Alert2.default, { severity: "error", sx: { mb: 1 }, onClose: () => setMemberError(null) }, memberError), members.length === 0 ? /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "body2", color: "text.secondary" }, "No members yet.") : /* @__PURE__ */ import_react5.default.createElement(import_List.default, { dense: true, disablePadding: true }, members.map((m) => /* @__PURE__ */ import_react5.default.createElement(
2192
2208
  import_ListItem.default,
2193
2209
  {
@@ -2286,7 +2302,7 @@ function rateTone(rate) {
2286
2302
  if (rate >= 0.9) return "warning";
2287
2303
  return "danger";
2288
2304
  }
2289
- var import_react6, import_Paper3, import_Box6, import_Typography6, import_TextField4, import_MenuItem2, import_Grid, import_Table2, import_TableBody2, import_TableCell2, import_TableContainer2, import_TableHead2, import_TableRow2, import_Skeleton3, import_recharts, TOP_N_MODELS, PERIOD_LS_KEY, PRESET_LABELS, fmtPct, ChartSkeleton, ChartOrFallback, SuccessRateCell, UsageStats;
2305
+ var import_react6, import_Paper3, import_Box6, import_Typography6, import_TextField4, import_MenuItem3, import_Grid, import_Table2, import_TableBody2, import_TableCell2, import_TableContainer2, import_TableHead2, import_TableRow2, import_Skeleton3, import_recharts, TOP_N_MODELS, PERIOD_LS_KEY, PRESET_LABELS, fmtPct, ChartSkeleton, ChartOrFallback, SuccessRateCell, UsageStats;
2290
2306
  var init_UsageStats = __esm({
2291
2307
  "src/components/UsageStats.tsx"() {
2292
2308
  "use strict";
@@ -2295,7 +2311,7 @@ var init_UsageStats = __esm({
2295
2311
  import_Box6 = __toESM(require("@mui/material/Box"));
2296
2312
  import_Typography6 = __toESM(require("@mui/material/Typography"));
2297
2313
  import_TextField4 = __toESM(require("@mui/material/TextField"));
2298
- import_MenuItem2 = __toESM(require("@mui/material/MenuItem"));
2314
+ import_MenuItem3 = __toESM(require("@mui/material/MenuItem"));
2299
2315
  import_Grid = __toESM(require("@mui/material/Grid"));
2300
2316
  import_Table2 = __toESM(require("@mui/material/Table"));
2301
2317
  import_TableBody2 = __toESM(require("@mui/material/TableBody"));
@@ -2500,7 +2516,7 @@ var init_UsageStats = __esm({
2500
2516
  onChange: (e) => handlePresetChange(e.target.value),
2501
2517
  sx: { minWidth: 160 }
2502
2518
  },
2503
- Object.keys(PRESET_LABELS).map((p) => /* @__PURE__ */ import_react6.default.createElement(import_MenuItem2.default, { key: p, value: p }, PRESET_LABELS[p]))
2519
+ Object.keys(PRESET_LABELS).map((p) => /* @__PURE__ */ import_react6.default.createElement(import_MenuItem3.default, { key: p, value: p }, PRESET_LABELS[p]))
2504
2520
  );
2505
2521
  return /* @__PURE__ */ import_react6.default.createElement(
2506
2522
  SectionCard,
@@ -2545,8 +2561,8 @@ var init_UsageStats = __esm({
2545
2561
  onChange: (e) => setSelectedModel(e.target.value),
2546
2562
  sx: { minWidth: 220 }
2547
2563
  },
2548
- /* @__PURE__ */ import_react6.default.createElement(import_MenuItem2.default, { value: "all" }, "All models"),
2549
- models.map((m) => /* @__PURE__ */ import_react6.default.createElement(import_MenuItem2.default, { key: m.model_name, value: m.model_name }, m.model_name))
2564
+ /* @__PURE__ */ import_react6.default.createElement(import_MenuItem3.default, { value: "all" }, "All models"),
2565
+ models.map((m) => /* @__PURE__ */ import_react6.default.createElement(import_MenuItem3.default, { key: m.model_name, value: m.model_name }, m.model_name))
2550
2566
  )
2551
2567
  ),
2552
2568
  tab === "costs" && /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { container: true, spacing: 2 }, /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react6.default.createElement(ChartCard, { title: "Daily spend by model", height: 260 }, /* @__PURE__ */ import_react6.default.createElement(ChartOrFallback, { loading, empty: modelSpendByDate.length === 0, height: 260 }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.AreaChart, { data: modelSpendByDate, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { tickFormatter: fmtUsdCompact, width: 56, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(
@@ -2886,7 +2902,7 @@ function fmtTokens(n) {
2886
2902
  if (n >= 1e3) return `${(n / 1e3).toFixed(0)}K`;
2887
2903
  return String(n);
2888
2904
  }
2889
- var import_react8, import_Box8, import_Table4, import_TableBody4, import_TableCell4, import_TableContainer4, import_TableHead4, import_TableRow4, import_Typography8, import_MenuItem3, import_Select, import_FormControl, import_InputLabel, import_ContentCopy, import_Tooltip, import_Snackbar, import_Alert3, import_styles5, ALL_PROXY_MODELS2, ModelsTable;
2905
+ var import_react8, import_Box8, import_Table4, import_TableBody4, import_TableCell4, import_TableContainer4, import_TableHead4, import_TableRow4, import_Typography8, import_MenuItem4, import_Select, import_FormControl, import_InputLabel, import_ContentCopy, import_Tooltip, import_Snackbar, import_Alert3, import_styles5, ALL_PROXY_MODELS2, ModelsTable;
2890
2906
  var init_ModelsTable = __esm({
2891
2907
  "src/components/ModelsTable.tsx"() {
2892
2908
  "use strict";
@@ -2899,7 +2915,7 @@ var init_ModelsTable = __esm({
2899
2915
  import_TableHead4 = __toESM(require("@mui/material/TableHead"));
2900
2916
  import_TableRow4 = __toESM(require("@mui/material/TableRow"));
2901
2917
  import_Typography8 = __toESM(require("@mui/material/Typography"));
2902
- import_MenuItem3 = __toESM(require("@mui/material/MenuItem"));
2918
+ import_MenuItem4 = __toESM(require("@mui/material/MenuItem"));
2903
2919
  import_Select = __toESM(require("@mui/material/Select"));
2904
2920
  import_FormControl = __toESM(require("@mui/material/FormControl"));
2905
2921
  import_InputLabel = __toESM(require("@mui/material/InputLabel"));
@@ -2953,7 +2969,7 @@ var init_ModelsTable = __esm({
2953
2969
  label: "Team",
2954
2970
  onChange: (e) => setSelectedTeamId(e.target.value)
2955
2971
  },
2956
- teams.map((t) => /* @__PURE__ */ import_react8.default.createElement(import_MenuItem3.default, { key: t.team_id, value: t.team_id }, t.team_alias ?? t.team_id))
2972
+ teams.map((t) => /* @__PURE__ */ import_react8.default.createElement(import_MenuItem4.default, { key: t.team_id, value: t.team_id }, t.team_alias ?? t.team_id))
2957
2973
  ))),
2958
2974
  loading && /* @__PURE__ */ import_react8.default.createElement(EmptyState, { message: "Loading models\u2026" }),
2959
2975
  !loading && !selectedTeamId && /* @__PURE__ */ import_react8.default.createElement(
@@ -3049,7 +3065,7 @@ function renderAuditLogBody(loading, entries) {
3049
3065
  }
3050
3066
  return entries.map((entry) => /* @__PURE__ */ import_react9.default.createElement(DetailRow, { key: entry.id, entry }));
3051
3067
  }
3052
- var import_react9, import_Box9, import_Typography9, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_TablePagination, import_TextField5, import_MenuItem4, import_Skeleton5, import_Collapse2, import_IconButton5, import_Alert4, import_styles6, import_icons_material6, import_react_use, ACTION_TONES, TABLE_LABELS, DetailRow, AuditLog;
3068
+ var import_react9, import_Box9, import_Typography9, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_TablePagination, import_TextField5, import_MenuItem5, import_Skeleton5, import_Collapse2, import_IconButton5, import_Alert4, import_styles6, import_icons_material6, import_react_use, ACTION_TONES, TABLE_LABELS, DetailRow, AuditLog;
3053
3069
  var init_AuditLog = __esm({
3054
3070
  "src/components/AuditLog.tsx"() {
3055
3071
  "use strict";
@@ -3064,7 +3080,7 @@ var init_AuditLog = __esm({
3064
3080
  import_TableRow5 = __toESM(require("@mui/material/TableRow"));
3065
3081
  import_TablePagination = __toESM(require("@mui/material/TablePagination"));
3066
3082
  import_TextField5 = __toESM(require("@mui/material/TextField"));
3067
- import_MenuItem4 = __toESM(require("@mui/material/MenuItem"));
3083
+ import_MenuItem5 = __toESM(require("@mui/material/MenuItem"));
3068
3084
  import_Skeleton5 = __toESM(require("@mui/material/Skeleton"));
3069
3085
  import_Collapse2 = __toESM(require("@mui/material/Collapse"));
3070
3086
  import_IconButton5 = __toESM(require("@mui/material/IconButton"));
@@ -3184,11 +3200,11 @@ var init_AuditLog = __esm({
3184
3200
  },
3185
3201
  sx: { minWidth: 150 }
3186
3202
  },
3187
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "" }, "All actions"),
3188
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "created" }, "Created"),
3189
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "updated" }, "Updated"),
3190
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "deleted" }, "Deleted"),
3191
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "blocked" }, "Blocked")
3203
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "" }, "All actions"),
3204
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "created" }, "Created"),
3205
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "updated" }, "Updated"),
3206
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "deleted" }, "Deleted"),
3207
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "blocked" }, "Blocked")
3192
3208
  ), /* @__PURE__ */ import_react9.default.createElement(
3193
3209
  import_TextField5.default,
3194
3210
  {
@@ -3202,12 +3218,12 @@ var init_AuditLog = __esm({
3202
3218
  },
3203
3219
  sx: { minWidth: 150 }
3204
3220
  },
3205
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "" }, "All tables"),
3206
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "LiteLLM_VerificationToken" }, "Key"),
3207
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "LiteLLM_TeamTable" }, "Team"),
3208
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "LiteLLM_TeamMembership" }, "Team member"),
3209
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "LiteLLM_ObjectPermissionTable" }, "Team access (KB / MCP)"),
3210
- /* @__PURE__ */ import_react9.default.createElement(import_MenuItem4.default, { value: "LiteLLM_UserTable" }, "User")
3221
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "" }, "All tables"),
3222
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "LiteLLM_VerificationToken" }, "Key"),
3223
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "LiteLLM_TeamTable" }, "Team"),
3224
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "LiteLLM_TeamMembership" }, "Team member"),
3225
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "LiteLLM_ObjectPermissionTable" }, "Team access (KB / MCP)"),
3226
+ /* @__PURE__ */ import_react9.default.createElement(import_MenuItem5.default, { value: "LiteLLM_UserTable" }, "User")
3211
3227
  ), /* @__PURE__ */ import_react9.default.createElement(
3212
3228
  import_TextField5.default,
3213
3229
  {
@@ -3774,7 +3790,7 @@ var import_Box11 = __toESM(require("@mui/material/Box"));
3774
3790
  var import_Typography11 = __toESM(require("@mui/material/Typography"));
3775
3791
  var import_FormControl2 = __toESM(require("@mui/material/FormControl"));
3776
3792
  var import_Select2 = __toESM(require("@mui/material/Select"));
3777
- var import_MenuItem5 = __toESM(require("@mui/material/MenuItem"));
3793
+ var import_MenuItem6 = __toESM(require("@mui/material/MenuItem"));
3778
3794
  var import_Grid2 = __toESM(require("@mui/material/Grid"));
3779
3795
  var import_CircularProgress5 = __toESM(require("@mui/material/CircularProgress"));
3780
3796
  var import_Alert6 = __toESM(require("@mui/material/Alert"));
@@ -3850,9 +3866,9 @@ var LiteLLMHomeWidget = ({
3850
3866
  onChange: (e) => setPeriod(e.target.value),
3851
3867
  displayEmpty: true
3852
3868
  },
3853
- /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "today" }, "Today"),
3854
- /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "7d" }, "7d"),
3855
- /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "30d" }, "30d")
3869
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem6.default, { value: "today" }, "Today"),
3870
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem6.default, { value: "7d" }, "7d"),
3871
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem6.default, { value: "30d" }, "30d")
3856
3872
  ))), loading && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 120 }, /* @__PURE__ */ import_react12.default.createElement(import_CircularProgress5.default, { size: 32 })), !loading && totalFailure && /* @__PURE__ */ import_react12.default.createElement(import_Alert6.default, { severity: "error", sx: { mt: 1 } }, usageError ?? "Failed to load usage data"), !loading && !totalFailure && /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, partialFailure && /* @__PURE__ */ import_react12.default.createElement(import_Alert6.default, { severity: "warning", sx: { mt: 1, mb: 1 } }, usageError ? `Usage data unavailable (${usageError}).` : "", keysError ? ` Key list unavailable (${keysError}).` : "", " Showing what loaded."), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { container: true, spacing: 2, sx: { mb: hasSparkline ? 1.5 : 0 } }, /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "USD Spent", value: fmtUsd(usage?.total_spend ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Tokens In", value: fmtInt(usage?.prompt_tokens ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Tokens Out", value: fmtInt(usage?.completion_tokens ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Keys", value: fmtInt(keys.length) }))), hasSparkline && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { height: 120 }, /* @__PURE__ */ import_react12.default.createElement(import_recharts3.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react12.default.createElement(import_recharts3.AreaChart, { data: dailyData, margin: { top: 4, right: 0, bottom: 0, left: 0 } }, /* @__PURE__ */ import_react12.default.createElement(
3857
3873
  import_recharts3.Area,
3858
3874
  {