@acarmisc/backstage-plugin-litellm 0.29.0 → 0.31.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/components/LiteLLMBudgetGauges.d.ts +26 -14
- package/dist/homeWidgetHelpers.d.ts +13 -0
- package/dist/index.cjs.js +338 -174
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.esm.js +341 -176
- package/dist/index.esm.js.map +3 -3
- package/dist/keyLabels.d.ts +15 -0
- package/package.json +3 -2
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:
|
|
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: {
|
|
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
|
)
|
|
@@ -1524,6 +1529,18 @@ function pruneCopy(n) {
|
|
|
1524
1529
|
}
|
|
1525
1530
|
return `Remove ${n} expired keys from the list. They already don't work.`;
|
|
1526
1531
|
}
|
|
1532
|
+
function blockButtonState(blocked, manage, unblock) {
|
|
1533
|
+
if (blocked) {
|
|
1534
|
+
return {
|
|
1535
|
+
label: unblock.denied ? "No permission to unblock keys" : "Unblock key",
|
|
1536
|
+
disabled: !unblock.allowed
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
return {
|
|
1540
|
+
label: manage.denied ? "No permission to block keys" : "Block key \u2014 suspends without revoking",
|
|
1541
|
+
disabled: !manage.allowed
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1527
1544
|
var init_keyLabels = __esm({
|
|
1528
1545
|
"src/keyLabels.ts"() {
|
|
1529
1546
|
"use strict";
|
|
@@ -1738,10 +1755,13 @@ var init_KeysTable = __esm({
|
|
|
1738
1755
|
}) => {
|
|
1739
1756
|
const managePermission = (0, import_plugin_permission_react.usePermission)({ permission: import_backstage_plugin_litellm_common.litellmKeyManagePermission });
|
|
1740
1757
|
const revokePermission = (0, import_plugin_permission_react.usePermission)({ permission: import_backstage_plugin_litellm_common.litellmKeyRevokePermission });
|
|
1758
|
+
const unblockPermission = (0, import_plugin_permission_react.usePermission)({ permission: import_backstage_plugin_litellm_common.litellmKeyUnblockPermission });
|
|
1741
1759
|
const canManageKeys = !managePermission.loading && managePermission.allowed;
|
|
1742
1760
|
const canRevokeKeys = !revokePermission.loading && revokePermission.allowed;
|
|
1743
1761
|
const manageDenied = !managePermission.loading && !managePermission.allowed;
|
|
1744
1762
|
const revokeDenied = !revokePermission.loading && !revokePermission.allowed;
|
|
1763
|
+
const canUnblockKeys = !unblockPermission.loading && unblockPermission.allowed;
|
|
1764
|
+
const unblockDenied = !unblockPermission.loading && !unblockPermission.allowed;
|
|
1745
1765
|
const [blockConfirmKey, setBlockConfirmKey] = (0, import_react4.useState)(null);
|
|
1746
1766
|
const [blockSubmitting, setBlockSubmitting] = (0, import_react4.useState)(false);
|
|
1747
1767
|
const [deleteConfirmKey, setDeleteConfirmKey] = (0, import_react4.useState)(null);
|
|
@@ -1860,6 +1880,11 @@ var init_KeysTable = __esm({
|
|
|
1860
1880
|
return filteredKeys.map((key) => {
|
|
1861
1881
|
const keyId = key.token ?? key.key;
|
|
1862
1882
|
const keyModels = key.models ?? [];
|
|
1883
|
+
const blockState = blockButtonState(
|
|
1884
|
+
key.blocked,
|
|
1885
|
+
{ allowed: canManageKeys, denied: manageDenied },
|
|
1886
|
+
{ allowed: canUnblockKeys, denied: unblockDenied }
|
|
1887
|
+
);
|
|
1863
1888
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1864
1889
|
import_TableRow.default,
|
|
1865
1890
|
{
|
|
@@ -1931,19 +1956,13 @@ var init_KeysTable = __esm({
|
|
|
1931
1956
|
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_icons_material2.Edit, { fontSize: "small" })
|
|
1932
1957
|
}
|
|
1933
1958
|
) }) }),
|
|
1934
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Tooltip.default, { describeChild: true, title: ((
|
|
1935
|
-
if (manageDenied) return "No permission to block keys";
|
|
1936
|
-
return key.blocked ? "Unblock key" : "Block key \u2014 suspends without revoking";
|
|
1937
|
-
})(), placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1959
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Tooltip.default, { describeChild: true, title: blockState.label, placement: "top", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1938
1960
|
import_IconButton.default,
|
|
1939
1961
|
{
|
|
1940
1962
|
size: "small",
|
|
1941
1963
|
onClick: () => handleToggleBlock(key),
|
|
1942
|
-
disabled: blockSubmitting ||
|
|
1943
|
-
"aria-label":
|
|
1944
|
-
if (manageDenied) return "No permission to block keys";
|
|
1945
|
-
return key.blocked ? "Unblock key" : "Block key \u2014 suspends without revoking";
|
|
1946
|
-
})(),
|
|
1964
|
+
disabled: blockSubmitting || blockState.disabled,
|
|
1965
|
+
"aria-label": blockState.label,
|
|
1947
1966
|
sx: quietIconButtonSx("warning"),
|
|
1948
1967
|
children: keyBlockIcon(blockSubmitting, key.blocked)
|
|
1949
1968
|
}
|
|
@@ -6563,6 +6582,7 @@ init_widgetState();
|
|
|
6563
6582
|
// src/homeWidgetHelpers.ts
|
|
6564
6583
|
init_format();
|
|
6565
6584
|
init_tokens();
|
|
6585
|
+
init_dates();
|
|
6566
6586
|
function rangeCaption(startDay, endDay) {
|
|
6567
6587
|
return `${fmtDateShort(startDay)} \u2013 ${fmtDateShort(endDay)}`;
|
|
6568
6588
|
}
|
|
@@ -6587,6 +6607,10 @@ function sparklineAriaLabel(points) {
|
|
|
6587
6607
|
const peakDate = fmtDateShort(maxPoint.date);
|
|
6588
6608
|
return `Daily spend over ${dayCount} day${dayCount === 1 ? "" : "s"}, total ${fmtUsd(total)}, peak ${fmtUsd(maxPoint.spend)} on ${peakDate}`;
|
|
6589
6609
|
}
|
|
6610
|
+
function spendOnDay(points, now = /* @__PURE__ */ new Date()) {
|
|
6611
|
+
const day = toLocalDay(now);
|
|
6612
|
+
return points.find((p) => p.date === day)?.spend ?? 0;
|
|
6613
|
+
}
|
|
6590
6614
|
function usageSummary(usage) {
|
|
6591
6615
|
if (!usage) {
|
|
6592
6616
|
return "$0.00 spent \xB7 0 in \xB7 0 out";
|
|
@@ -6815,7 +6839,76 @@ function resetLabel(limit) {
|
|
|
6815
6839
|
const window2 = fmtBudgetDuration(limit.budgetDuration);
|
|
6816
6840
|
return window2 ? `resets ${window2}` : "never resets";
|
|
6817
6841
|
}
|
|
6818
|
-
var
|
|
6842
|
+
var Tag = ({ children, tone, title }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6843
|
+
import_Typography17.default,
|
|
6844
|
+
{
|
|
6845
|
+
title,
|
|
6846
|
+
sx: (theme) => ({
|
|
6847
|
+
fontSize: 10.5,
|
|
6848
|
+
fontWeight: 700,
|
|
6849
|
+
letterSpacing: "0.08em",
|
|
6850
|
+
textTransform: "uppercase",
|
|
6851
|
+
lineHeight: 1.3,
|
|
6852
|
+
color: tone ? toneColor(theme, tone) : theme.palette.text.secondary,
|
|
6853
|
+
whiteSpace: "nowrap",
|
|
6854
|
+
overflow: "hidden",
|
|
6855
|
+
textOverflow: "ellipsis"
|
|
6856
|
+
}),
|
|
6857
|
+
children
|
|
6858
|
+
}
|
|
6859
|
+
);
|
|
6860
|
+
var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0, flex: 1 }, children: [
|
|
6861
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", alignItems: "center", gap: 0.625, minWidth: 0 }, children: [
|
|
6862
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6863
|
+
import_Box19.default,
|
|
6864
|
+
{
|
|
6865
|
+
sx: (theme) => ({
|
|
6866
|
+
width: 6,
|
|
6867
|
+
height: 6,
|
|
6868
|
+
borderRadius: "50%",
|
|
6869
|
+
bgcolor: toneColor(theme, tone),
|
|
6870
|
+
flexShrink: 0
|
|
6871
|
+
})
|
|
6872
|
+
}
|
|
6873
|
+
),
|
|
6874
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { children: label })
|
|
6875
|
+
] }),
|
|
6876
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6877
|
+
import_Typography17.default,
|
|
6878
|
+
{
|
|
6879
|
+
title,
|
|
6880
|
+
sx: {
|
|
6881
|
+
fontSize: 19,
|
|
6882
|
+
fontWeight: 700,
|
|
6883
|
+
lineHeight: 1.15,
|
|
6884
|
+
mt: 0.25,
|
|
6885
|
+
fontVariantNumeric: "tabular-nums",
|
|
6886
|
+
whiteSpace: "nowrap",
|
|
6887
|
+
overflow: "hidden",
|
|
6888
|
+
textOverflow: "ellipsis"
|
|
6889
|
+
},
|
|
6890
|
+
children: value
|
|
6891
|
+
}
|
|
6892
|
+
),
|
|
6893
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6894
|
+
import_Typography17.default,
|
|
6895
|
+
{
|
|
6896
|
+
variant: "caption",
|
|
6897
|
+
color: "text.secondary",
|
|
6898
|
+
sx: {
|
|
6899
|
+
display: "block",
|
|
6900
|
+
mt: 0.25,
|
|
6901
|
+
fontSize: 10.5,
|
|
6902
|
+
minHeight: 14,
|
|
6903
|
+
whiteSpace: "nowrap",
|
|
6904
|
+
overflow: "hidden",
|
|
6905
|
+
textOverflow: "ellipsis"
|
|
6906
|
+
},
|
|
6907
|
+
children: hint ?? ""
|
|
6908
|
+
}
|
|
6909
|
+
)
|
|
6910
|
+
] });
|
|
6911
|
+
var LevelRow = ({
|
|
6819
6912
|
gauge,
|
|
6820
6913
|
size,
|
|
6821
6914
|
keysHref
|
|
@@ -6824,14 +6917,42 @@ var LevelGauge = ({
|
|
|
6824
6917
|
const limit = gauge.limit;
|
|
6825
6918
|
const tone = limit ? budgetTone2(limit.pct) : "neutral";
|
|
6826
6919
|
const extra = gauge.kind === "key" ? Math.max(0, gauge.count - 1) : 0;
|
|
6920
|
+
const overCap = Boolean(limit && limit.pct > 100);
|
|
6921
|
+
const subNote = () => {
|
|
6922
|
+
if (overCap) return "Over cap";
|
|
6923
|
+
if (extra > 0 && keysHref) {
|
|
6924
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
6925
|
+
import_Typography17.default,
|
|
6926
|
+
{
|
|
6927
|
+
component: import_core_components5.Link,
|
|
6928
|
+
to: keysHref,
|
|
6929
|
+
variant: "caption",
|
|
6930
|
+
sx: {
|
|
6931
|
+
fontSize: 10.5,
|
|
6932
|
+
color: "primary.main",
|
|
6933
|
+
textDecoration: "none",
|
|
6934
|
+
"&:hover": { textDecoration: "underline" }
|
|
6935
|
+
},
|
|
6936
|
+
children: [
|
|
6937
|
+
"+",
|
|
6938
|
+
extra,
|
|
6939
|
+
" more"
|
|
6940
|
+
]
|
|
6941
|
+
}
|
|
6942
|
+
);
|
|
6943
|
+
}
|
|
6944
|
+
return limit?.sublabel ?? null;
|
|
6945
|
+
};
|
|
6827
6946
|
const gaugeAriaLabel = limit ? `${name} budget used: ${Math.round(limit.pct)}%` : `${name} \u2014 no cap`;
|
|
6828
6947
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
6829
6948
|
import_Box19.default,
|
|
6830
6949
|
{
|
|
6831
6950
|
sx: {
|
|
6832
|
-
display: "
|
|
6833
|
-
|
|
6951
|
+
display: "grid",
|
|
6952
|
+
gridTemplateColumns: "auto minmax(0, 1fr) auto",
|
|
6834
6953
|
alignItems: "center",
|
|
6954
|
+
gap: 1.25,
|
|
6955
|
+
py: 0.75,
|
|
6835
6956
|
minWidth: 0
|
|
6836
6957
|
},
|
|
6837
6958
|
children: [
|
|
@@ -6845,84 +6966,109 @@ var LevelGauge = ({
|
|
|
6845
6966
|
ariaLabel: gaugeAriaLabel
|
|
6846
6967
|
}
|
|
6847
6968
|
),
|
|
6848
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.
|
|
6849
|
-
|
|
6850
|
-
{
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6969
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0 }, children: [
|
|
6970
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { tone: tone === "warning" || tone === "danger" ? tone : void 0, children: name }),
|
|
6971
|
+
limit ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
6972
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6973
|
+
import_Typography17.default,
|
|
6974
|
+
{
|
|
6975
|
+
variant: "caption",
|
|
6976
|
+
title: limit.sublabel ? `${limit.label} \xB7 ${limit.sublabel}` : limit.label,
|
|
6977
|
+
sx: {
|
|
6978
|
+
display: "block",
|
|
6979
|
+
fontSize: 11.5,
|
|
6980
|
+
fontWeight: 600,
|
|
6981
|
+
lineHeight: 1.35,
|
|
6982
|
+
overflow: "hidden",
|
|
6983
|
+
textOverflow: "ellipsis",
|
|
6984
|
+
whiteSpace: "nowrap"
|
|
6985
|
+
},
|
|
6986
|
+
children: limit.label
|
|
6987
|
+
}
|
|
6988
|
+
),
|
|
6989
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6990
|
+
import_Typography17.default,
|
|
6991
|
+
{
|
|
6992
|
+
variant: "caption",
|
|
6993
|
+
color: overCap ? "error" : "text.secondary",
|
|
6994
|
+
sx: {
|
|
6995
|
+
display: "block",
|
|
6996
|
+
fontSize: 10.5,
|
|
6997
|
+
fontWeight: overCap ? 700 : void 0,
|
|
6998
|
+
lineHeight: 1.35,
|
|
6999
|
+
overflow: "hidden",
|
|
7000
|
+
textOverflow: "ellipsis",
|
|
7001
|
+
whiteSpace: "nowrap"
|
|
7002
|
+
},
|
|
7003
|
+
children: subNote()
|
|
7004
|
+
}
|
|
7005
|
+
)
|
|
7006
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6864
7007
|
import_Typography17.default,
|
|
6865
7008
|
{
|
|
6866
7009
|
variant: "caption",
|
|
6867
|
-
|
|
7010
|
+
color: "text.secondary",
|
|
6868
7011
|
sx: {
|
|
6869
|
-
|
|
6870
|
-
fontSize:
|
|
6871
|
-
|
|
6872
|
-
maxWidth: "100%",
|
|
7012
|
+
display: "block",
|
|
7013
|
+
fontSize: 10.5,
|
|
7014
|
+
lineHeight: 1.35,
|
|
6873
7015
|
overflow: "hidden",
|
|
6874
7016
|
textOverflow: "ellipsis",
|
|
6875
7017
|
whiteSpace: "nowrap"
|
|
6876
7018
|
},
|
|
6877
|
-
children:
|
|
7019
|
+
children: none
|
|
6878
7020
|
}
|
|
6879
|
-
)
|
|
7021
|
+
)
|
|
7022
|
+
] }),
|
|
7023
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minWidth: 0, textAlign: "right" }, children: [
|
|
6880
7024
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6881
7025
|
import_Typography17.default,
|
|
6882
7026
|
{
|
|
6883
|
-
|
|
6884
|
-
color: "text.secondary",
|
|
7027
|
+
title: limit ? `${fmtUsd(limit.spend)} of ${fmtUsd(limit.budget)}` : void 0,
|
|
6885
7028
|
sx: {
|
|
6886
|
-
|
|
7029
|
+
display: "block",
|
|
7030
|
+
fontSize: 12.5,
|
|
7031
|
+
fontWeight: 600,
|
|
7032
|
+
lineHeight: 1.35,
|
|
6887
7033
|
fontVariantNumeric: "tabular-nums",
|
|
6888
|
-
|
|
7034
|
+
whiteSpace: "nowrap",
|
|
7035
|
+
overflow: "hidden",
|
|
7036
|
+
textOverflow: "ellipsis",
|
|
7037
|
+
color: limit ? void 0 : "text.secondary"
|
|
6889
7038
|
},
|
|
6890
|
-
children:
|
|
7039
|
+
children: amountCaption(limit)
|
|
6891
7040
|
}
|
|
6892
7041
|
),
|
|
6893
|
-
|
|
7042
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6894
7043
|
import_Typography17.default,
|
|
6895
7044
|
{
|
|
6896
|
-
component: import_core_components5.Link,
|
|
6897
|
-
to: keysHref,
|
|
6898
7045
|
variant: "caption",
|
|
7046
|
+
color: "text.secondary",
|
|
6899
7047
|
sx: {
|
|
7048
|
+
display: "block",
|
|
6900
7049
|
fontSize: 10.5,
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
7050
|
+
lineHeight: 1.35,
|
|
7051
|
+
whiteSpace: "nowrap",
|
|
7052
|
+
overflow: "hidden",
|
|
7053
|
+
textOverflow: "ellipsis"
|
|
6904
7054
|
},
|
|
6905
|
-
children:
|
|
6906
|
-
"+",
|
|
6907
|
-
extra,
|
|
6908
|
-
" more"
|
|
6909
|
-
]
|
|
7055
|
+
children: amountNote(limit)
|
|
6910
7056
|
}
|
|
6911
|
-
)
|
|
6912
|
-
] })
|
|
6913
|
-
import_Typography17.default,
|
|
6914
|
-
{
|
|
6915
|
-
variant: "caption",
|
|
6916
|
-
color: "text.secondary",
|
|
6917
|
-
sx: { mt: 0.25, fontSize: 10.5, textAlign: "center" },
|
|
6918
|
-
children: none
|
|
6919
|
-
}
|
|
6920
|
-
)
|
|
7057
|
+
)
|
|
7058
|
+
] })
|
|
6921
7059
|
]
|
|
6922
7060
|
}
|
|
6923
7061
|
);
|
|
6924
7062
|
};
|
|
6925
|
-
|
|
7063
|
+
function amountCaption(limit) {
|
|
7064
|
+
if (!limit) return "";
|
|
7065
|
+
return limit.hidden ? `${Math.round(limit.pct)}%` : spendCaption(limit);
|
|
7066
|
+
}
|
|
7067
|
+
function amountNote(limit) {
|
|
7068
|
+
if (!limit) return "";
|
|
7069
|
+
return limit.hidden ? "hidden by admin" : resetLabel(limit);
|
|
7070
|
+
}
|
|
7071
|
+
var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, maxBudget }) => {
|
|
6926
7072
|
const renderPlot = () => {
|
|
6927
7073
|
if (loading) {
|
|
6928
7074
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "rectangular", width: "100%", height: "100%" });
|
|
@@ -6968,99 +7114,70 @@ var UsageMiniChart = ({ data, totalSpend, loading, height, usageUnavailable = fa
|
|
|
6968
7114
|
)
|
|
6969
7115
|
] }) });
|
|
6970
7116
|
};
|
|
6971
|
-
const
|
|
6972
|
-
if (loading)
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
import_Box19.default,
|
|
7021
|
-
{
|
|
7022
|
-
sx: {
|
|
7023
|
-
display: "flex",
|
|
7024
|
-
flexDirection: "column",
|
|
7025
|
-
alignItems: "center",
|
|
7026
|
-
minWidth: 0
|
|
7027
|
-
},
|
|
7028
|
-
role: "img",
|
|
7029
|
-
"aria-label": sparklineAriaLabel(data),
|
|
7030
|
-
children: [
|
|
7031
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { height, width: "100%" }, children: renderPlot() }),
|
|
7032
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7033
|
-
import_Typography17.default,
|
|
7034
|
-
{
|
|
7035
|
-
sx: (theme) => ({
|
|
7036
|
-
mt: 0.75,
|
|
7037
|
-
fontSize: 10.5,
|
|
7038
|
-
fontWeight: 700,
|
|
7039
|
-
letterSpacing: "0.08em",
|
|
7040
|
-
textTransform: "uppercase",
|
|
7041
|
-
color: theme.palette.text.secondary
|
|
7042
|
-
}),
|
|
7043
|
-
children: "Spend (MTD)"
|
|
7044
|
-
}
|
|
7045
|
-
),
|
|
7046
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7047
|
-
import_Typography17.default,
|
|
7048
|
-
{
|
|
7049
|
-
variant: "caption",
|
|
7050
|
-
color: "text.secondary",
|
|
7051
|
-
sx: { mt: 0.25, fontSize: 10.5 },
|
|
7052
|
-
children: mtdCaption()
|
|
7053
|
-
}
|
|
7054
|
-
),
|
|
7055
|
-
renderCaption()
|
|
7056
|
-
]
|
|
7057
|
-
}
|
|
7058
|
-
);
|
|
7117
|
+
const caption = (() => {
|
|
7118
|
+
if (loading) return "\u2026";
|
|
7119
|
+
if (usageUnavailable) return USAGE_UNAVAILABLE_MSG;
|
|
7120
|
+
if (data.length === 0) return "No spend this month";
|
|
7121
|
+
return mtdCaption();
|
|
7122
|
+
})();
|
|
7123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { role: "img", "aria-label": sparklineAriaLabel(data), sx: { minWidth: 0 }, children: [
|
|
7124
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { height, width: "100%" }, children: renderPlot() }),
|
|
7125
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
7126
|
+
import_Box19.default,
|
|
7127
|
+
{
|
|
7128
|
+
sx: {
|
|
7129
|
+
display: "flex",
|
|
7130
|
+
alignItems: "baseline",
|
|
7131
|
+
justifyContent: "space-between",
|
|
7132
|
+
gap: 1,
|
|
7133
|
+
mt: 0.5,
|
|
7134
|
+
minWidth: 0
|
|
7135
|
+
},
|
|
7136
|
+
children: [
|
|
7137
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { display: "flex", alignItems: "baseline", gap: 0.75, minWidth: 0 }, children: [
|
|
7138
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Tag, { children: "Spent (mtd)" }),
|
|
7139
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7140
|
+
import_Typography17.default,
|
|
7141
|
+
{
|
|
7142
|
+
variant: "caption",
|
|
7143
|
+
color: "text.secondary",
|
|
7144
|
+
sx: { fontSize: 10.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
7145
|
+
children: caption
|
|
7146
|
+
}
|
|
7147
|
+
)
|
|
7148
|
+
] }),
|
|
7149
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7150
|
+
import_Typography17.default,
|
|
7151
|
+
{
|
|
7152
|
+
title: loading || usageUnavailable ? void 0 : `${fmtUsd(mtdSpend)} spent month to date`,
|
|
7153
|
+
sx: {
|
|
7154
|
+
fontSize: 12.5,
|
|
7155
|
+
fontWeight: 700,
|
|
7156
|
+
fontVariantNumeric: "tabular-nums",
|
|
7157
|
+
whiteSpace: "nowrap"
|
|
7158
|
+
},
|
|
7159
|
+
children: loading || usageUnavailable ? "\u2014" : fmtUsd(mtdSpend)
|
|
7160
|
+
}
|
|
7161
|
+
)
|
|
7162
|
+
]
|
|
7163
|
+
}
|
|
7164
|
+
)
|
|
7165
|
+
] });
|
|
7059
7166
|
};
|
|
7167
|
+
function statValue(loading, unavailable, value) {
|
|
7168
|
+
if (loading) return "\u2026";
|
|
7169
|
+
if (unavailable) return "\u2014";
|
|
7170
|
+
return value;
|
|
7171
|
+
}
|
|
7172
|
+
function statHint(loading, unavailable, hint) {
|
|
7173
|
+
if (loading) return void 0;
|
|
7174
|
+
if (unavailable) return USAGE_UNAVAILABLE_MSG;
|
|
7175
|
+
return hint;
|
|
7176
|
+
}
|
|
7060
7177
|
var LiteLLMBudgetGauges = ({
|
|
7061
7178
|
title = "Budget",
|
|
7062
7179
|
bare = false,
|
|
7063
|
-
size =
|
|
7180
|
+
size = 56,
|
|
7064
7181
|
keysHref,
|
|
7065
7182
|
moduleHref: propModuleHref,
|
|
7066
7183
|
onCreateKey,
|
|
@@ -7077,7 +7194,7 @@ var LiteLLMBudgetGauges = ({
|
|
|
7077
7194
|
const api = (0, import_core_plugin_api7.useApi)(liteLlmApiRef);
|
|
7078
7195
|
const theme = (0, import_styles13.useTheme)();
|
|
7079
7196
|
const isSmallScreen = (0, import_useMediaQuery.default)(theme.breakpoints.down("sm"));
|
|
7080
|
-
const gaugeSize = isSmallScreen ?
|
|
7197
|
+
const gaugeSize = isSmallScreen ? Math.min(48, size) : size;
|
|
7081
7198
|
const expandedRegionId = (0, import_react15.useId)();
|
|
7082
7199
|
const moduleRouteRef = (0, import_frontend_plugin_api6.useRouteRef)(rootRouteRef);
|
|
7083
7200
|
const moduleHref = propModuleHref ?? moduleRouteRef?.();
|
|
@@ -7152,6 +7269,12 @@ var LiteLLMBudgetGauges = ({
|
|
|
7152
7269
|
}),
|
|
7153
7270
|
[loading, profileError, user, usageError, keys]
|
|
7154
7271
|
);
|
|
7272
|
+
const today = /* @__PURE__ */ new Date();
|
|
7273
|
+
const todaySpend = spendOnDay(dailySpend, today);
|
|
7274
|
+
const yesterday = new Date(today);
|
|
7275
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
7276
|
+
const yesterdaySpend = dailySpend.some((d) => d.date === toLocalDay(yesterday)) ? spendOnDay(dailySpend, yesterday) : null;
|
|
7277
|
+
const todayHint = yesterdaySpend === null ? void 0 : `vs ${fmtUsd(yesterdaySpend)} yesterday`;
|
|
7155
7278
|
const summaryText = headline.count === 0 ? "no limits apply" : `${headline.count} limit${headline.count === 1 ? "" : "s"}`;
|
|
7156
7279
|
const resolvedCtas = (0, import_react15.useMemo)(() => {
|
|
7157
7280
|
return resolveCtas({
|
|
@@ -7212,29 +7335,70 @@ var LiteLLMBudgetGauges = ({
|
|
|
7212
7335
|
}
|
|
7213
7336
|
)
|
|
7214
7337
|
] }),
|
|
7215
|
-
viewState.kind === "loading" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { display: "flex",
|
|
7216
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "circular", width: size, height: size
|
|
7217
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.
|
|
7218
|
-
|
|
7219
|
-
|
|
7338
|
+
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: [
|
|
7339
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "circular", width: size, height: size }),
|
|
7340
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { flex: 1 }, children: [
|
|
7341
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "70%", height: 12, sx: { mb: 0.25 } }),
|
|
7342
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: "45%", height: 11 })
|
|
7343
|
+
] }),
|
|
7344
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton8.default, { variant: "text", width: 64, height: 12 })
|
|
7220
7345
|
] }, i)) }),
|
|
7221
7346
|
viewState.kind === "error" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: viewState.message }),
|
|
7222
7347
|
viewState.kind === "unprovisioned" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: UNPROVISIONED_MSG }),
|
|
7223
7348
|
viewState.kind === "ready" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
7224
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
|
|
7237
|
-
|
|
7349
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
7350
|
+
import_Box19.default,
|
|
7351
|
+
{
|
|
7352
|
+
sx: {
|
|
7353
|
+
display: "flex",
|
|
7354
|
+
alignItems: "stretch",
|
|
7355
|
+
gap: 2,
|
|
7356
|
+
mb: 1.25,
|
|
7357
|
+
minWidth: 0
|
|
7358
|
+
},
|
|
7359
|
+
children: [
|
|
7360
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7361
|
+
InlineStat,
|
|
7362
|
+
{
|
|
7363
|
+
label: "Today spent",
|
|
7364
|
+
tone: "accent",
|
|
7365
|
+
value: statValue(usageLoading, viewState.usageUnavailable, fmtUsd(todaySpend)),
|
|
7366
|
+
hint: statHint(usageLoading, viewState.usageUnavailable, todayHint),
|
|
7367
|
+
title: usageLoading || viewState.usageUnavailable ? void 0 : "Spend since local midnight"
|
|
7368
|
+
}
|
|
7369
|
+
),
|
|
7370
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { width: "1px", bgcolor: "divider", flexShrink: 0 } }),
|
|
7371
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7372
|
+
InlineStat,
|
|
7373
|
+
{
|
|
7374
|
+
label: "Month to date",
|
|
7375
|
+
value: statValue(usageLoading, viewState.usageUnavailable, fmtUsd(mtdSpend)),
|
|
7376
|
+
hint: statHint(usageLoading, viewState.usageUnavailable, mtdCaption()),
|
|
7377
|
+
title: usageLoading || viewState.usageUnavailable ? void 0 : "Spend from the 1st of this month"
|
|
7378
|
+
}
|
|
7379
|
+
)
|
|
7380
|
+
]
|
|
7381
|
+
}
|
|
7382
|
+
),
|
|
7383
|
+
/* @__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)(
|
|
7384
|
+
import_Box19.default,
|
|
7385
|
+
{
|
|
7386
|
+
sx: i === 0 ? void 0 : { borderTop: "1px solid", borderColor: "divider" },
|
|
7387
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LevelRow, { gauge, size: gaugeSize, keysHref: keysTabHref })
|
|
7388
|
+
},
|
|
7389
|
+
gauge.kind
|
|
7390
|
+
)) }),
|
|
7391
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { mt: 1.25 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7392
|
+
SpendStrip,
|
|
7393
|
+
{
|
|
7394
|
+
data: dailySpend,
|
|
7395
|
+
mtdSpend,
|
|
7396
|
+
loading: usageLoading,
|
|
7397
|
+
height: gaugeSize,
|
|
7398
|
+
usageUnavailable: viewState.usageUnavailable,
|
|
7399
|
+
maxBudget: user?.max_budget ?? void 0
|
|
7400
|
+
}
|
|
7401
|
+
) }),
|
|
7238
7402
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Collapse4.default, { in: isExpanded, unmountOnExit: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7239
7403
|
import_Box19.default,
|
|
7240
7404
|
{
|