@acarmisc/backstage-plugin-litellm 0.30.0 → 0.31.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.
package/dist/index.cjs.js CHANGED
@@ -1060,16 +1060,21 @@ var init_Gauge = __esm({
1060
1060
  fontSize: size <= 64 ? 15 : 18,
1061
1061
  fontWeight: 700,
1062
1062
  fontVariantNumeric: "tabular-nums",
1063
- color: "text.primary"
1063
+ color: isOverCap ? "currentColor" : "text.primary"
1064
1064
  },
1065
- children: isOverCap ? "Over cap" : label ?? `${Math.round(value)}%`
1065
+ children: label ?? `${Math.round(value)}%`
1066
1066
  }
1067
1067
  ),
1068
1068
  caption && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1069
1069
  import_Typography3.default,
1070
1070
  {
1071
1071
  variant: "caption",
1072
- sx: { fontSize: 9.5, color: "text.secondary", mt: 0.25 },
1072
+ sx: {
1073
+ fontSize: 9.5,
1074
+ color: "text.secondary",
1075
+ mt: 0.25,
1076
+ whiteSpace: "nowrap"
1077
+ },
1073
1078
  children: caption
1074
1079
  }
1075
1080
  )
@@ -2570,9 +2575,22 @@ var init_KeyFormDialog = __esm({
2570
2575
  setCloseWithoutCopyConfirm(false);
2571
2576
  setTouched({});
2572
2577
  setSubmitAttempted(false);
2573
- onGetConfig().then(setConfig).catch(() => setConfig(null));
2574
2578
  }
2575
- }, [open, isCreate, keyToEdit, username, keyGenerationSettings?.allowUnlimitedBudget, onGetConfig]);
2579
+ }, [open, isCreate, keyToEdit, username, keyGenerationSettings?.allowUnlimitedBudget]);
2580
+ const onGetConfigRef = (0, import_react6.useRef)(onGetConfig);
2581
+ onGetConfigRef.current = onGetConfig;
2582
+ (0, import_react6.useEffect)(() => {
2583
+ if (!open) return void 0;
2584
+ let cancelled = false;
2585
+ onGetConfigRef.current().then((c) => {
2586
+ if (!cancelled) setConfig(c);
2587
+ }).catch(() => {
2588
+ if (!cancelled) setConfig(null);
2589
+ });
2590
+ return () => {
2591
+ cancelled = true;
2592
+ };
2593
+ }, [open]);
2576
2594
  const allowUnlimitedBudget = keyGenerationSettings?.allowUnlimitedBudget ?? false;
2577
2595
  const teamRequired = keyGenerationSettings?.teamRequired ?? true;
2578
2596
  const formData = isCreate ? generateForm : editFormState;
@@ -6068,6 +6086,7 @@ var init_LiteLLMPage = __esm({
6068
6086
  ]);
6069
6087
  return allModels.filter((m) => allowed.has(m.model_name));
6070
6088
  }, [allModels, userInfo, teams]);
6089
+ const getConfig = (0, import_react13.useCallback)(() => api.getConfig(), [api]);
6071
6090
  const handleGenerateKey = (0, import_react13.useCallback)(
6072
6091
  async (request) => {
6073
6092
  try {
@@ -6393,7 +6412,7 @@ var init_LiteLLMPage = __esm({
6393
6412
  onCreateKey: handleGenerateKey,
6394
6413
  onUpdateKey: handleUpdateKey,
6395
6414
  onResetKeySpend: handleResetKeySpend,
6396
- onGetConfig: () => api.getConfig()
6415
+ onGetConfig: getConfig
6397
6416
  }
6398
6417
  ),
6399
6418
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
@@ -6577,6 +6596,7 @@ init_widgetState();
6577
6596
  // src/homeWidgetHelpers.ts
6578
6597
  init_format();
6579
6598
  init_tokens();
6599
+ init_dates();
6580
6600
  function rangeCaption(startDay, endDay) {
6581
6601
  return `${fmtDateShort(startDay)} \u2013 ${fmtDateShort(endDay)}`;
6582
6602
  }
@@ -6601,6 +6621,10 @@ function sparklineAriaLabel(points) {
6601
6621
  const peakDate = fmtDateShort(maxPoint.date);
6602
6622
  return `Daily spend over ${dayCount} day${dayCount === 1 ? "" : "s"}, total ${fmtUsd(total)}, peak ${fmtUsd(maxPoint.spend)} on ${peakDate}`;
6603
6623
  }
6624
+ function spendOnDay(points, now = /* @__PURE__ */ new Date()) {
6625
+ const day = toLocalDay(now);
6626
+ return points.find((p) => p.date === day)?.spend ?? 0;
6627
+ }
6604
6628
  function usageSummary(usage) {
6605
6629
  if (!usage) {
6606
6630
  return "$0.00 spent \xB7 0 in \xB7 0 out";
@@ -6829,7 +6853,76 @@ function resetLabel(limit) {
6829
6853
  const window2 = fmtBudgetDuration(limit.budgetDuration);
6830
6854
  return window2 ? `resets ${window2}` : "never resets";
6831
6855
  }
6832
- var LevelGauge = ({
6856
+ var Tag = ({ children, tone, title }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6857
+ import_Typography17.default,
6858
+ {
6859
+ title,
6860
+ sx: (theme) => ({
6861
+ fontSize: 10.5,
6862
+ fontWeight: 700,
6863
+ letterSpacing: "0.08em",
6864
+ textTransform: "uppercase",
6865
+ lineHeight: 1.3,
6866
+ color: tone ? toneColor(theme, tone) : theme.palette.text.secondary,
6867
+ whiteSpace: "nowrap",
6868
+ overflow: "hidden",
6869
+ textOverflow: "ellipsis"
6870
+ }),
6871
+ children
6872
+ }
6873
+ );
6874
+ var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0, flex: 1 }, children: [
6875
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", alignItems: "center", gap: 0.625, minWidth: 0 }, children: [
6876
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6877
+ import_Box19.default,
6878
+ {
6879
+ sx: (theme) => ({
6880
+ width: 6,
6881
+ height: 6,
6882
+ borderRadius: "50%",
6883
+ bgcolor: toneColor(theme, tone),
6884
+ flexShrink: 0
6885
+ })
6886
+ }
6887
+ ),
6888
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { children: label })
6889
+ ] }),
6890
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6891
+ import_Typography17.default,
6892
+ {
6893
+ title,
6894
+ sx: {
6895
+ fontSize: 19,
6896
+ fontWeight: 700,
6897
+ lineHeight: 1.15,
6898
+ mt: 0.25,
6899
+ fontVariantNumeric: "tabular-nums",
6900
+ whiteSpace: "nowrap",
6901
+ overflow: "hidden",
6902
+ textOverflow: "ellipsis"
6903
+ },
6904
+ children: value
6905
+ }
6906
+ ),
6907
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6908
+ import_Typography17.default,
6909
+ {
6910
+ variant: "caption",
6911
+ color: "text.secondary",
6912
+ sx: {
6913
+ display: "block",
6914
+ mt: 0.25,
6915
+ fontSize: 10.5,
6916
+ minHeight: 14,
6917
+ whiteSpace: "nowrap",
6918
+ overflow: "hidden",
6919
+ textOverflow: "ellipsis"
6920
+ },
6921
+ children: hint ?? ""
6922
+ }
6923
+ )
6924
+ ] });
6925
+ var LevelRow = ({
6833
6926
  gauge,
6834
6927
  size,
6835
6928
  keysHref
@@ -6838,14 +6931,42 @@ var LevelGauge = ({
6838
6931
  const limit = gauge.limit;
6839
6932
  const tone = limit ? budgetTone2(limit.pct) : "neutral";
6840
6933
  const extra = gauge.kind === "key" ? Math.max(0, gauge.count - 1) : 0;
6934
+ const overCap = Boolean(limit && limit.pct > 100);
6935
+ const subNote = () => {
6936
+ if (overCap) return "Over cap";
6937
+ if (extra > 0 && keysHref) {
6938
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6939
+ import_Typography17.default,
6940
+ {
6941
+ component: import_core_components5.Link,
6942
+ to: keysHref,
6943
+ variant: "caption",
6944
+ sx: {
6945
+ fontSize: 10.5,
6946
+ color: "primary.main",
6947
+ textDecoration: "none",
6948
+ "&:hover": { textDecoration: "underline" }
6949
+ },
6950
+ children: [
6951
+ "+",
6952
+ extra,
6953
+ " more"
6954
+ ]
6955
+ }
6956
+ );
6957
+ }
6958
+ return limit?.sublabel ?? null;
6959
+ };
6841
6960
  const gaugeAriaLabel = limit ? `${name} budget used: ${Math.round(limit.pct)}%` : `${name} \u2014 no cap`;
6842
6961
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6843
6962
  import_Box19.default,
6844
6963
  {
6845
6964
  sx: {
6846
- display: "flex",
6847
- flexDirection: "column",
6965
+ display: "grid",
6966
+ gridTemplateColumns: "auto minmax(0, 1fr) auto",
6848
6967
  alignItems: "center",
6968
+ gap: 1.25,
6969
+ py: 0.75,
6849
6970
  minWidth: 0
6850
6971
  },
6851
6972
  children: [
@@ -6859,84 +6980,109 @@ var LevelGauge = ({
6859
6980
  ariaLabel: gaugeAriaLabel
6860
6981
  }
6861
6982
  ),
6862
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6863
- import_Typography17.default,
6864
- {
6865
- sx: (theme) => ({
6866
- mt: 0.75,
6867
- fontSize: 10.5,
6868
- fontWeight: 700,
6869
- letterSpacing: "0.08em",
6870
- textTransform: "uppercase",
6871
- color: tone === "neutral" ? theme.palette.text.secondary : void 0
6872
- }),
6873
- children: name
6874
- }
6875
- ),
6876
- limit ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6877
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6983
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0 }, children: [
6984
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { tone: tone === "warning" || tone === "danger" ? tone : void 0, children: name }),
6985
+ limit ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6986
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6987
+ import_Typography17.default,
6988
+ {
6989
+ variant: "caption",
6990
+ title: limit.sublabel ? `${limit.label} \xB7 ${limit.sublabel}` : limit.label,
6991
+ sx: {
6992
+ display: "block",
6993
+ fontSize: 11.5,
6994
+ fontWeight: 600,
6995
+ lineHeight: 1.35,
6996
+ overflow: "hidden",
6997
+ textOverflow: "ellipsis",
6998
+ whiteSpace: "nowrap"
6999
+ },
7000
+ children: limit.label
7001
+ }
7002
+ ),
7003
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7004
+ import_Typography17.default,
7005
+ {
7006
+ variant: "caption",
7007
+ color: overCap ? "error" : "text.secondary",
7008
+ sx: {
7009
+ display: "block",
7010
+ fontSize: 10.5,
7011
+ fontWeight: overCap ? 700 : void 0,
7012
+ lineHeight: 1.35,
7013
+ overflow: "hidden",
7014
+ textOverflow: "ellipsis",
7015
+ whiteSpace: "nowrap"
7016
+ },
7017
+ children: subNote()
7018
+ }
7019
+ )
7020
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6878
7021
  import_Typography17.default,
6879
7022
  {
6880
7023
  variant: "caption",
6881
- title: limit.sublabel ? `${limit.label} \xB7 ${limit.sublabel}` : limit.label,
7024
+ color: "text.secondary",
6882
7025
  sx: {
6883
- mt: 0.25,
6884
- fontSize: 11,
6885
- fontWeight: 600,
6886
- maxWidth: "100%",
7026
+ display: "block",
7027
+ fontSize: 10.5,
7028
+ lineHeight: 1.35,
6887
7029
  overflow: "hidden",
6888
7030
  textOverflow: "ellipsis",
6889
7031
  whiteSpace: "nowrap"
6890
7032
  },
6891
- children: limit.label
7033
+ children: none
6892
7034
  }
6893
- ),
7035
+ )
7036
+ ] }),
7037
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0, textAlign: "right" }, children: [
6894
7038
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6895
7039
  import_Typography17.default,
6896
7040
  {
6897
- variant: "caption",
6898
- color: "text.secondary",
7041
+ title: limit ? `${fmtUsd(limit.spend)} of ${fmtUsd(limit.budget)}` : void 0,
6899
7042
  sx: {
6900
- fontSize: 10.5,
7043
+ display: "block",
7044
+ fontSize: 12.5,
7045
+ fontWeight: 600,
7046
+ lineHeight: 1.35,
6901
7047
  fontVariantNumeric: "tabular-nums",
6902
- textAlign: "center"
7048
+ whiteSpace: "nowrap",
7049
+ overflow: "hidden",
7050
+ textOverflow: "ellipsis",
7051
+ color: limit ? void 0 : "text.secondary"
6903
7052
  },
6904
- children: spendCaption(limit)
7053
+ children: amountCaption(limit)
6905
7054
  }
6906
7055
  ),
6907
- extra > 0 && keysHref ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7056
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6908
7057
  import_Typography17.default,
6909
7058
  {
6910
- component: import_core_components5.Link,
6911
- to: keysHref,
6912
7059
  variant: "caption",
7060
+ color: "text.secondary",
6913
7061
  sx: {
7062
+ display: "block",
6914
7063
  fontSize: 10.5,
6915
- color: "primary.main",
6916
- textDecoration: "none",
6917
- "&:hover": { textDecoration: "underline" }
7064
+ lineHeight: 1.35,
7065
+ whiteSpace: "nowrap",
7066
+ overflow: "hidden",
7067
+ textOverflow: "ellipsis"
6918
7068
  },
6919
- children: [
6920
- "+",
6921
- extra,
6922
- " more"
6923
- ]
7069
+ children: amountNote(limit)
6924
7070
  }
6925
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 10.5 }, children: resetLabel(limit) })
6926
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6927
- import_Typography17.default,
6928
- {
6929
- variant: "caption",
6930
- color: "text.secondary",
6931
- sx: { mt: 0.25, fontSize: 10.5, textAlign: "center" },
6932
- children: none
6933
- }
6934
- )
7071
+ )
7072
+ ] })
6935
7073
  ]
6936
7074
  }
6937
7075
  );
6938
7076
  };
6939
- var UsageMiniChart = ({ data, totalSpend, loading, height, usageUnavailable = false, maxBudget }) => {
7077
+ function amountCaption(limit) {
7078
+ if (!limit) return "";
7079
+ return limit.hidden ? `${Math.round(limit.pct)}%` : spendCaption(limit);
7080
+ }
7081
+ function amountNote(limit) {
7082
+ if (!limit) return "";
7083
+ return limit.hidden ? "hidden by admin" : resetLabel(limit);
7084
+ }
7085
+ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, maxBudget }) => {
6940
7086
  const renderPlot = () => {
6941
7087
  if (loading) {
6942
7088
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "rectangular", width: "100%", height: "100%" });
@@ -6982,99 +7128,70 @@ var UsageMiniChart = ({ data, totalSpend, loading, height, usageUnavailable = fa
6982
7128
  )
6983
7129
  ] }) });
6984
7130
  };
6985
- const renderCaption = () => {
6986
- if (loading) {
6987
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "caption", color: "text.secondary", sx: { mt: 0.25, fontSize: 11 }, children: "\u2026" });
6988
- }
6989
- if (usageUnavailable) {
6990
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6991
- import_Typography17.default,
6992
- {
6993
- variant: "caption",
6994
- color: "text.secondary",
6995
- sx: { mt: 0.25, fontSize: 10.5, textAlign: "center" },
6996
- children: USAGE_UNAVAILABLE_MSG
6997
- }
6998
- );
6999
- }
7000
- if (data.length === 0) {
7001
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7002
- import_Typography17.default,
7003
- {
7004
- variant: "caption",
7005
- color: "text.secondary",
7006
- sx: { mt: 0.25, fontSize: 10.5, textAlign: "center" },
7007
- children: "No spend this month"
7008
- }
7009
- );
7010
- }
7011
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
7012
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7013
- import_Typography17.default,
7014
- {
7015
- variant: "caption",
7016
- title: `${fmtUsd(totalSpend)} spent month to date`,
7017
- sx: {
7018
- mt: 0.25,
7019
- fontSize: 11,
7020
- fontWeight: 600,
7021
- maxWidth: "100%",
7022
- overflow: "hidden",
7023
- textOverflow: "ellipsis",
7024
- whiteSpace: "nowrap",
7025
- fontVariantNumeric: "tabular-nums"
7026
- },
7027
- children: fmtUsd(totalSpend)
7028
- }
7029
- ),
7030
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 10.5 }, children: "month to date" })
7031
- ] });
7032
- };
7033
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7034
- import_Box19.default,
7035
- {
7036
- sx: {
7037
- display: "flex",
7038
- flexDirection: "column",
7039
- alignItems: "center",
7040
- minWidth: 0
7041
- },
7042
- role: "img",
7043
- "aria-label": sparklineAriaLabel(data),
7044
- children: [
7045
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { height, width: "100%" }, children: renderPlot() }),
7046
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7047
- import_Typography17.default,
7048
- {
7049
- sx: (theme) => ({
7050
- mt: 0.75,
7051
- fontSize: 10.5,
7052
- fontWeight: 700,
7053
- letterSpacing: "0.08em",
7054
- textTransform: "uppercase",
7055
- color: theme.palette.text.secondary
7056
- }),
7057
- children: "Spend (MTD)"
7058
- }
7059
- ),
7060
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7061
- import_Typography17.default,
7062
- {
7063
- variant: "caption",
7064
- color: "text.secondary",
7065
- sx: { mt: 0.25, fontSize: 10.5 },
7066
- children: mtdCaption()
7067
- }
7068
- ),
7069
- renderCaption()
7070
- ]
7071
- }
7072
- );
7131
+ const caption = (() => {
7132
+ if (loading) return "\u2026";
7133
+ if (usageUnavailable) return USAGE_UNAVAILABLE_MSG;
7134
+ if (data.length === 0) return "No spend this month";
7135
+ return mtdCaption();
7136
+ })();
7137
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { role: "img", "aria-label": sparklineAriaLabel(data), sx: { minWidth: 0 }, children: [
7138
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { height, width: "100%" }, children: renderPlot() }),
7139
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7140
+ import_Box19.default,
7141
+ {
7142
+ sx: {
7143
+ display: "flex",
7144
+ alignItems: "baseline",
7145
+ justifyContent: "space-between",
7146
+ gap: 1,
7147
+ mt: 0.5,
7148
+ minWidth: 0
7149
+ },
7150
+ children: [
7151
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", alignItems: "baseline", gap: 0.75, minWidth: 0 }, children: [
7152
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { children: "Spent (mtd)" }),
7153
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7154
+ import_Typography17.default,
7155
+ {
7156
+ variant: "caption",
7157
+ color: "text.secondary",
7158
+ sx: { fontSize: 10.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
7159
+ children: caption
7160
+ }
7161
+ )
7162
+ ] }),
7163
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7164
+ import_Typography17.default,
7165
+ {
7166
+ title: loading || usageUnavailable ? void 0 : `${fmtUsd(mtdSpend)} spent month to date`,
7167
+ sx: {
7168
+ fontSize: 12.5,
7169
+ fontWeight: 700,
7170
+ fontVariantNumeric: "tabular-nums",
7171
+ whiteSpace: "nowrap"
7172
+ },
7173
+ children: loading || usageUnavailable ? "\u2014" : fmtUsd(mtdSpend)
7174
+ }
7175
+ )
7176
+ ]
7177
+ }
7178
+ )
7179
+ ] });
7073
7180
  };
7181
+ function statValue(loading, unavailable, value) {
7182
+ if (loading) return "\u2026";
7183
+ if (unavailable) return "\u2014";
7184
+ return value;
7185
+ }
7186
+ function statHint(loading, unavailable, hint) {
7187
+ if (loading) return void 0;
7188
+ if (unavailable) return USAGE_UNAVAILABLE_MSG;
7189
+ return hint;
7190
+ }
7074
7191
  var LiteLLMBudgetGauges = ({
7075
7192
  title = "Budget",
7076
7193
  bare = false,
7077
- size = 72,
7194
+ size = 56,
7078
7195
  keysHref,
7079
7196
  moduleHref: propModuleHref,
7080
7197
  onCreateKey,
@@ -7091,7 +7208,7 @@ var LiteLLMBudgetGauges = ({
7091
7208
  const api = (0, import_core_plugin_api7.useApi)(liteLlmApiRef);
7092
7209
  const theme = (0, import_styles13.useTheme)();
7093
7210
  const isSmallScreen = (0, import_useMediaQuery.default)(theme.breakpoints.down("sm"));
7094
- const gaugeSize = isSmallScreen ? 56 : size;
7211
+ const gaugeSize = isSmallScreen ? Math.min(48, size) : size;
7095
7212
  const expandedRegionId = (0, import_react15.useId)();
7096
7213
  const moduleRouteRef = (0, import_frontend_plugin_api6.useRouteRef)(rootRouteRef);
7097
7214
  const moduleHref = propModuleHref ?? moduleRouteRef?.();
@@ -7166,6 +7283,12 @@ var LiteLLMBudgetGauges = ({
7166
7283
  }),
7167
7284
  [loading, profileError, user, usageError, keys]
7168
7285
  );
7286
+ const today = /* @__PURE__ */ new Date();
7287
+ const todaySpend = spendOnDay(dailySpend, today);
7288
+ const yesterday = new Date(today);
7289
+ yesterday.setDate(yesterday.getDate() - 1);
7290
+ const yesterdaySpend = dailySpend.some((d) => d.date === toLocalDay(yesterday)) ? spendOnDay(dailySpend, yesterday) : null;
7291
+ const todayHint = yesterdaySpend === null ? void 0 : `vs ${fmtUsd(yesterdaySpend)} yesterday`;
7169
7292
  const summaryText = headline.count === 0 ? "no limits apply" : `${headline.count} limit${headline.count === 1 ? "" : "s"}`;
7170
7293
  const resolvedCtas = (0, import_react15.useMemo)(() => {
7171
7294
  return resolveCtas({
@@ -7226,29 +7349,70 @@ var LiteLLMBudgetGauges = ({
7226
7349
  }
7227
7350
  )
7228
7351
  ] }),
7229
- viewState.kind === "loading" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { display: "flex", alignItems: "flex-start", gap: 1, minHeight: size }, children: [0, 1, 2, 3].map((i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", flexDirection: "column", alignItems: "center", flex: 1 }, children: [
7230
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "circular", width: size, height: size, sx: { mb: 0.75 } }),
7231
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "100%", height: 12, sx: { mb: 0.25 } }),
7232
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "80%", height: 11, sx: { mb: 0.25 } }),
7233
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "70%", height: 10.5 })
7352
+ viewState.kind === "loading" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { display: "flex", flexDirection: "column", gap: 1.25, minHeight: size }, children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", alignItems: "center", gap: 1.25 }, children: [
7353
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "circular", width: size, height: size }),
7354
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { flex: 1 }, children: [
7355
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "70%", height: 12, sx: { mb: 0.25 } }),
7356
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "45%", height: 11 })
7357
+ ] }),
7358
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: 64, height: 12 })
7234
7359
  ] }, i)) }),
7235
7360
  viewState.kind === "error" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: viewState.message }),
7236
7361
  viewState.kind === "unprovisioned" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: UNPROVISIONED_MSG }),
7237
7362
  viewState.kind === "ready" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
7238
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(76px, 1fr))", gap: 1 }, children: [
7239
- gauges.map((gauge) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LevelGauge, { gauge, size: gaugeSize, keysHref: keysTabHref }, gauge.kind)),
7240
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7241
- UsageMiniChart,
7242
- {
7243
- data: dailySpend,
7244
- totalSpend: mtdSpend,
7245
- loading: usageLoading,
7246
- height: gaugeSize,
7247
- usageUnavailable: viewState.usageUnavailable,
7248
- maxBudget: user?.max_budget ?? void 0
7249
- }
7250
- )
7251
- ] }),
7363
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7364
+ import_Box19.default,
7365
+ {
7366
+ sx: {
7367
+ display: "flex",
7368
+ alignItems: "stretch",
7369
+ gap: 2,
7370
+ mb: 1.25,
7371
+ minWidth: 0
7372
+ },
7373
+ children: [
7374
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7375
+ InlineStat,
7376
+ {
7377
+ label: "Today spent",
7378
+ tone: "accent",
7379
+ value: statValue(usageLoading, viewState.usageUnavailable, fmtUsd(todaySpend)),
7380
+ hint: statHint(usageLoading, viewState.usageUnavailable, todayHint),
7381
+ title: usageLoading || viewState.usageUnavailable ? void 0 : "Spend since local midnight"
7382
+ }
7383
+ ),
7384
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { width: "1px", bgcolor: "divider", flexShrink: 0 } }),
7385
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7386
+ InlineStat,
7387
+ {
7388
+ label: "Month to date",
7389
+ value: statValue(usageLoading, viewState.usageUnavailable, fmtUsd(mtdSpend)),
7390
+ hint: statHint(usageLoading, viewState.usageUnavailable, mtdCaption()),
7391
+ title: usageLoading || viewState.usageUnavailable ? void 0 : "Spend from the 1st of this month"
7392
+ }
7393
+ )
7394
+ ]
7395
+ }
7396
+ ),
7397
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { borderTop: "1px solid", borderColor: "divider" }, children: gauges.map((gauge, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7398
+ import_Box19.default,
7399
+ {
7400
+ sx: i === 0 ? void 0 : { borderTop: "1px solid", borderColor: "divider" },
7401
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LevelRow, { gauge, size: gaugeSize, keysHref: keysTabHref })
7402
+ },
7403
+ gauge.kind
7404
+ )) }),
7405
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { mt: 1.25 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7406
+ SpendStrip,
7407
+ {
7408
+ data: dailySpend,
7409
+ mtdSpend,
7410
+ loading: usageLoading,
7411
+ height: gaugeSize,
7412
+ usageUnavailable: viewState.usageUnavailable,
7413
+ maxBudget: user?.max_budget ?? void 0
7414
+ }
7415
+ ) }),
7252
7416
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Collapse4.default, { in: isExpanded, unmountOnExit: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7253
7417
  import_Box19.default,
7254
7418
  {