@acarmisc/backstage-plugin-litellm 0.35.0 → 0.37.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/api.d.ts +9 -0
- package/dist/components/ConnectPage.d.ts +7 -0
- package/dist/connect.d.ts +10 -0
- package/dist/index.cjs.js +294 -150
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.esm.js +279 -135
- package/dist/index.esm.js.map +4 -4
- package/dist/plugin.d.ts +40 -0
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -257,6 +257,10 @@ var init_api = __esm({
|
|
|
257
257
|
async listModels() {
|
|
258
258
|
return this.get("/models");
|
|
259
259
|
}
|
|
260
|
+
/** Mints (or rotates) the caller's connect-flow key, optionally bound to one of their teams. */
|
|
261
|
+
async connectLocalClient(redirectUri, team) {
|
|
262
|
+
return this.post("/opencode/connect", { redirect_uri: redirectUri, team });
|
|
263
|
+
}
|
|
260
264
|
async getTeams() {
|
|
261
265
|
return this.get("/teams");
|
|
262
266
|
}
|
|
@@ -6730,6 +6734,136 @@ var init_LiteLLMPage = __esm({
|
|
|
6730
6734
|
}
|
|
6731
6735
|
});
|
|
6732
6736
|
|
|
6737
|
+
// src/connect.ts
|
|
6738
|
+
function isLoopbackCallback(uri) {
|
|
6739
|
+
if (!uri) return false;
|
|
6740
|
+
try {
|
|
6741
|
+
const url = new URL(uri);
|
|
6742
|
+
return url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1") && url.pathname === "/callback" && url.search === "" && url.hash === "";
|
|
6743
|
+
} catch {
|
|
6744
|
+
return false;
|
|
6745
|
+
}
|
|
6746
|
+
}
|
|
6747
|
+
function postToLoopback(redirectUri, fields) {
|
|
6748
|
+
const form = document.createElement("form");
|
|
6749
|
+
form.method = "POST";
|
|
6750
|
+
form.action = redirectUri;
|
|
6751
|
+
for (const [name, value] of fields) {
|
|
6752
|
+
const input = document.createElement("input");
|
|
6753
|
+
input.type = "hidden";
|
|
6754
|
+
input.name = name;
|
|
6755
|
+
input.value = value;
|
|
6756
|
+
form.appendChild(input);
|
|
6757
|
+
}
|
|
6758
|
+
document.body.appendChild(form);
|
|
6759
|
+
form.submit();
|
|
6760
|
+
}
|
|
6761
|
+
function initialTeams(all, have) {
|
|
6762
|
+
const missing = all.filter((id) => !have.has(id));
|
|
6763
|
+
return new Set(have.size ? missing : all);
|
|
6764
|
+
}
|
|
6765
|
+
var init_connect = __esm({
|
|
6766
|
+
"src/connect.ts"() {
|
|
6767
|
+
"use strict";
|
|
6768
|
+
}
|
|
6769
|
+
});
|
|
6770
|
+
|
|
6771
|
+
// src/components/ConnectPage.tsx
|
|
6772
|
+
var ConnectPage_exports = {};
|
|
6773
|
+
__export(ConnectPage_exports, {
|
|
6774
|
+
ConnectPage: () => ConnectPage
|
|
6775
|
+
});
|
|
6776
|
+
var import_react14, import_Alert7, import_Box18, import_Button8, import_Checkbox3, import_FormControlLabel3, import_FormGroup, import_Paper9, import_Typography16, import_react_router_dom2, import_react_use3, import_core_plugin_api6, import_core_components4, import_jsx_runtime19, ConnectPage;
|
|
6777
|
+
var init_ConnectPage = __esm({
|
|
6778
|
+
"src/components/ConnectPage.tsx"() {
|
|
6779
|
+
"use strict";
|
|
6780
|
+
import_react14 = require("react");
|
|
6781
|
+
import_Alert7 = __toESM(require("@mui/material/Alert"));
|
|
6782
|
+
import_Box18 = __toESM(require("@mui/material/Box"));
|
|
6783
|
+
import_Button8 = __toESM(require("@mui/material/Button"));
|
|
6784
|
+
import_Checkbox3 = __toESM(require("@mui/material/Checkbox"));
|
|
6785
|
+
import_FormControlLabel3 = __toESM(require("@mui/material/FormControlLabel"));
|
|
6786
|
+
import_FormGroup = __toESM(require("@mui/material/FormGroup"));
|
|
6787
|
+
import_Paper9 = __toESM(require("@mui/material/Paper"));
|
|
6788
|
+
import_Typography16 = __toESM(require("@mui/material/Typography"));
|
|
6789
|
+
import_react_router_dom2 = require("react-router-dom");
|
|
6790
|
+
import_react_use3 = require("react-use");
|
|
6791
|
+
import_core_plugin_api6 = require("@backstage/core-plugin-api");
|
|
6792
|
+
import_core_components4 = require("@backstage/core-components");
|
|
6793
|
+
init_api();
|
|
6794
|
+
init_connect();
|
|
6795
|
+
import_jsx_runtime19 = require("react/jsx-runtime");
|
|
6796
|
+
ConnectPage = () => {
|
|
6797
|
+
const api = (0, import_core_plugin_api6.useApi)(liteLlmApiRef);
|
|
6798
|
+
const [params] = (0, import_react_router_dom2.useSearchParams)();
|
|
6799
|
+
const redirectUri = params.get("redirect_uri");
|
|
6800
|
+
const state = params.get("state") ?? "";
|
|
6801
|
+
const client = params.get("client") || "a local application";
|
|
6802
|
+
const have = new Set((params.get("have") ?? "").split(",").filter(Boolean));
|
|
6803
|
+
const teams = (0, import_react_use3.useAsync)(() => api.getTeams(), [api]);
|
|
6804
|
+
const [selected, setSelected] = (0, import_react14.useState)();
|
|
6805
|
+
const [busy, setBusy] = (0, import_react14.useState)(false);
|
|
6806
|
+
const [error, setError] = (0, import_react14.useState)();
|
|
6807
|
+
if (!isLoopbackCallback(redirectUri)) {
|
|
6808
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_core_components4.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Alert7.default, { severity: "error", children: "Invalid connection link: redirect_uri must be http://localhost:<port>/callback." }) });
|
|
6809
|
+
}
|
|
6810
|
+
if (teams.loading) return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_core_components4.Progress, {});
|
|
6811
|
+
const all = teams.value ?? [];
|
|
6812
|
+
const chosen = selected ?? initialTeams(all.map((t) => t.team_id), have);
|
|
6813
|
+
const toggle = (id) => {
|
|
6814
|
+
const next = new Set(chosen);
|
|
6815
|
+
if (!next.delete(id)) next.add(id);
|
|
6816
|
+
setSelected(next);
|
|
6817
|
+
};
|
|
6818
|
+
const connect = async () => {
|
|
6819
|
+
setBusy(true);
|
|
6820
|
+
setError(void 0);
|
|
6821
|
+
try {
|
|
6822
|
+
const ids = all.length ? all.filter((t) => chosen.has(t.team_id)).map((t) => t.team_id) : [void 0];
|
|
6823
|
+
const keys = [];
|
|
6824
|
+
for (const id of ids) keys.push(["key", (await api.connectLocalClient(redirectUri, id)).key]);
|
|
6825
|
+
postToLoopback(redirectUri, [["state", state], ...keys]);
|
|
6826
|
+
} catch (e) {
|
|
6827
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
6828
|
+
setBusy(false);
|
|
6829
|
+
}
|
|
6830
|
+
};
|
|
6831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_core_components4.Content, { children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Box18.default, { maxWidth: 520, mx: "auto", mt: 4, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_Paper9.default, { sx: { p: 3 }, children: [
|
|
6832
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_Typography16.default, { variant: "h5", gutterBottom: true, children: [
|
|
6833
|
+
"Connect ",
|
|
6834
|
+
client
|
|
6835
|
+
] }),
|
|
6836
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_Typography16.default, { variant: "body2", color: "text.secondary", paragraph: true, children: [
|
|
6837
|
+
client,
|
|
6838
|
+
" will receive an API key for each selected team. Selecting a team that is already connected replaces its key, also on your other devices."
|
|
6839
|
+
] }),
|
|
6840
|
+
teams.error && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_Alert7.default, { severity: "error", children: [
|
|
6841
|
+
"Could not load your teams: ",
|
|
6842
|
+
teams.error.message
|
|
6843
|
+
] }),
|
|
6844
|
+
all.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_FormGroup.default, { sx: { mb: 2 }, children: all.map((t) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
6845
|
+
import_FormControlLabel3.default,
|
|
6846
|
+
{
|
|
6847
|
+
control: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Checkbox3.default, { checked: chosen.has(t.team_id), onChange: () => toggle(t.team_id) }),
|
|
6848
|
+
label: `${t.team_alias ?? t.team_id}${have.has(t.team_id) ? " (already connected)" : ""}`
|
|
6849
|
+
},
|
|
6850
|
+
t.team_id
|
|
6851
|
+
)) }),
|
|
6852
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Alert7.default, { severity: "error", sx: { mb: 2 }, children: error }),
|
|
6853
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
6854
|
+
import_Button8.default,
|
|
6855
|
+
{
|
|
6856
|
+
variant: "contained",
|
|
6857
|
+
onClick: connect,
|
|
6858
|
+
disabled: busy || !!teams.error || all.length > 0 && chosen.size === 0,
|
|
6859
|
+
children: busy ? "Connecting\u2026" : "Connect"
|
|
6860
|
+
}
|
|
6861
|
+
)
|
|
6862
|
+
] }) }) });
|
|
6863
|
+
};
|
|
6864
|
+
}
|
|
6865
|
+
});
|
|
6866
|
+
|
|
6733
6867
|
// src/index.ts
|
|
6734
6868
|
var index_exports = {};
|
|
6735
6869
|
__export(index_exports, {
|
|
@@ -6761,7 +6895,7 @@ var import_icons_material10 = require("@mui/icons-material");
|
|
|
6761
6895
|
var import_frontend_plugin_api4 = require("@backstage/frontend-plugin-api");
|
|
6762
6896
|
init_api();
|
|
6763
6897
|
init_routes();
|
|
6764
|
-
var
|
|
6898
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
6765
6899
|
var liteLlmApi = import_frontend_plugin_api4.ApiBlueprint.make({
|
|
6766
6900
|
params: (defineParams) => defineParams({
|
|
6767
6901
|
api: liteLlmApiRef,
|
|
@@ -6773,11 +6907,21 @@ var liteLlmPage = import_frontend_plugin_api4.PageBlueprint.make({
|
|
|
6773
6907
|
params: {
|
|
6774
6908
|
path: "/litellm",
|
|
6775
6909
|
title: "LiteLLM",
|
|
6776
|
-
icon: /* @__PURE__ */ (0,
|
|
6910
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_icons_material10.TrendingUp, {}),
|
|
6777
6911
|
routeRef: rootRouteRef,
|
|
6778
6912
|
loader: async () => {
|
|
6779
6913
|
const { LiteLLMPage: LiteLLMPage2 } = await Promise.resolve().then(() => (init_LiteLLMPage(), LiteLLMPage_exports));
|
|
6780
|
-
return /* @__PURE__ */ (0,
|
|
6914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LiteLLMPage2, {});
|
|
6915
|
+
}
|
|
6916
|
+
}
|
|
6917
|
+
});
|
|
6918
|
+
var liteLlmConnectPage = import_frontend_plugin_api4.PageBlueprint.make({
|
|
6919
|
+
name: "connect",
|
|
6920
|
+
params: {
|
|
6921
|
+
path: "/litellm/connect",
|
|
6922
|
+
loader: async () => {
|
|
6923
|
+
const { ConnectPage: ConnectPage2 } = await Promise.resolve().then(() => (init_ConnectPage(), ConnectPage_exports));
|
|
6924
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ConnectPage2, {});
|
|
6781
6925
|
}
|
|
6782
6926
|
}
|
|
6783
6927
|
});
|
|
@@ -6786,7 +6930,7 @@ var litellmPlugin = (0, import_frontend_plugin_api4.createFrontendPlugin)({
|
|
|
6786
6930
|
routes: {
|
|
6787
6931
|
root: rootRouteRef
|
|
6788
6932
|
},
|
|
6789
|
-
extensions: [liteLlmApi, liteLlmPage]
|
|
6933
|
+
extensions: [liteLlmApi, liteLlmPage, liteLlmConnectPage]
|
|
6790
6934
|
});
|
|
6791
6935
|
|
|
6792
6936
|
// src/index.ts
|
|
@@ -6797,18 +6941,18 @@ init_UsageStats();
|
|
|
6797
6941
|
init_TeamUsage();
|
|
6798
6942
|
|
|
6799
6943
|
// src/components/LiteLLMHomeWidget.tsx
|
|
6800
|
-
var
|
|
6801
|
-
var
|
|
6802
|
-
var
|
|
6803
|
-
var
|
|
6944
|
+
var import_react15 = require("react");
|
|
6945
|
+
var import_Paper10 = __toESM(require("@mui/material/Paper"));
|
|
6946
|
+
var import_Box19 = __toESM(require("@mui/material/Box"));
|
|
6947
|
+
var import_Typography17 = __toESM(require("@mui/material/Typography"));
|
|
6804
6948
|
var import_FormControl2 = __toESM(require("@mui/material/FormControl"));
|
|
6805
6949
|
var import_Select2 = __toESM(require("@mui/material/Select"));
|
|
6806
6950
|
var import_MenuItem6 = __toESM(require("@mui/material/MenuItem"));
|
|
6807
6951
|
var import_Skeleton7 = __toESM(require("@mui/material/Skeleton"));
|
|
6808
6952
|
var import_recharts3 = require("recharts");
|
|
6809
|
-
var
|
|
6953
|
+
var import_core_plugin_api7 = require("@backstage/core-plugin-api");
|
|
6810
6954
|
var import_frontend_plugin_api5 = require("@backstage/frontend-plugin-api");
|
|
6811
|
-
var
|
|
6955
|
+
var import_core_components5 = require("@backstage/core-components");
|
|
6812
6956
|
init_useLiteLLMProfile();
|
|
6813
6957
|
init_api();
|
|
6814
6958
|
init_routes();
|
|
@@ -6860,7 +7004,7 @@ function usageSummary(usage) {
|
|
|
6860
7004
|
}
|
|
6861
7005
|
|
|
6862
7006
|
// src/components/LiteLLMHomeWidget.tsx
|
|
6863
|
-
var
|
|
7007
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
6864
7008
|
function presetToDateRange(preset) {
|
|
6865
7009
|
const end = /* @__PURE__ */ new Date();
|
|
6866
7010
|
const start = /* @__PURE__ */ new Date();
|
|
@@ -6878,14 +7022,14 @@ var LiteLLMHomeWidget = ({
|
|
|
6878
7022
|
title = "LiteLLM Usage",
|
|
6879
7023
|
bare = false
|
|
6880
7024
|
}) => {
|
|
6881
|
-
const api = (0,
|
|
7025
|
+
const api = (0, import_core_plugin_api7.useApi)(liteLlmApiRef);
|
|
6882
7026
|
const moduleRouteRef = (0, import_frontend_plugin_api5.useRouteRef)(rootRouteRef);
|
|
6883
7027
|
const { userInfo, keys, loading: profileLoading, error: profileError } = useLiteLLMProfile();
|
|
6884
|
-
const [period, setPeriod] = (0,
|
|
6885
|
-
const [usageLoading, setUsageLoading] = (0,
|
|
6886
|
-
const [usageError, setUsageError] = (0,
|
|
6887
|
-
const [usage, setUsage] = (0,
|
|
6888
|
-
(0,
|
|
7028
|
+
const [period, setPeriod] = (0, import_react15.useState)(defaultPeriod);
|
|
7029
|
+
const [usageLoading, setUsageLoading] = (0, import_react15.useState)(true);
|
|
7030
|
+
const [usageError, setUsageError] = (0, import_react15.useState)(null);
|
|
7031
|
+
const [usage, setUsage] = (0, import_react15.useState)(null);
|
|
7032
|
+
(0, import_react15.useEffect)(() => {
|
|
6889
7033
|
let cancelled = false;
|
|
6890
7034
|
setUsageLoading(true);
|
|
6891
7035
|
setUsageError(null);
|
|
@@ -6907,7 +7051,7 @@ var LiteLLMHomeWidget = ({
|
|
|
6907
7051
|
cancelled = true;
|
|
6908
7052
|
};
|
|
6909
7053
|
}, [api, period]);
|
|
6910
|
-
const viewState = (0,
|
|
7054
|
+
const viewState = (0, import_react15.useMemo)(
|
|
6911
7055
|
() => widgetViewState({
|
|
6912
7056
|
loading: profileLoading || usageLoading,
|
|
6913
7057
|
error: profileError,
|
|
@@ -6917,7 +7061,7 @@ var LiteLLMHomeWidget = ({
|
|
|
6917
7061
|
}),
|
|
6918
7062
|
[profileLoading, usageLoading, profileError, userInfo, usageError, keys]
|
|
6919
7063
|
);
|
|
6920
|
-
const Wrapper = bare ?
|
|
7064
|
+
const Wrapper = bare ? import_Box19.default : import_Paper10.default;
|
|
6921
7065
|
const partialFailure = !usageLoading && usageError && usage;
|
|
6922
7066
|
const dailyData = (usage?.daily_usage ?? []).map((d) => ({
|
|
6923
7067
|
date: d.date,
|
|
@@ -6929,10 +7073,10 @@ var LiteLLMHomeWidget = ({
|
|
|
6929
7073
|
const endDate = toLocalDay(end);
|
|
6930
7074
|
const dateRangeCaption = rangeCaption(startDate, endDate);
|
|
6931
7075
|
const sparklineAriaLabelText = sparklineAriaLabel(dailyData);
|
|
6932
|
-
return /* @__PURE__ */ (0,
|
|
6933
|
-
/* @__PURE__ */ (0,
|
|
6934
|
-
!bare && /* @__PURE__ */ (0,
|
|
6935
|
-
/* @__PURE__ */ (0,
|
|
7076
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Wrapper, { sx: bare ? { height: "100%" } : { p: 2, height: "100%" }, children: [
|
|
7077
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { display: "flex", justifyContent: bare ? "flex-end" : "space-between", alignItems: "center", mb: 1.5, children: [
|
|
7078
|
+
!bare && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "h6", children: title }),
|
|
7079
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_FormControl2.default, { size: "small", sx: { minWidth: 90 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
6936
7080
|
import_Select2.default,
|
|
6937
7081
|
{
|
|
6938
7082
|
value: period,
|
|
@@ -6940,23 +7084,23 @@ var LiteLLMHomeWidget = ({
|
|
|
6940
7084
|
displayEmpty: true,
|
|
6941
7085
|
inputProps: { "aria-label": "Usage period" },
|
|
6942
7086
|
children: [
|
|
6943
|
-
/* @__PURE__ */ (0,
|
|
6944
|
-
/* @__PURE__ */ (0,
|
|
6945
|
-
/* @__PURE__ */ (0,
|
|
7087
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem6.default, { value: "today", children: "Today" }),
|
|
7088
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem6.default, { value: "7d", children: "7d" }),
|
|
7089
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem6.default, { value: "30d", children: "30d" })
|
|
6946
7090
|
]
|
|
6947
7091
|
}
|
|
6948
7092
|
) })
|
|
6949
7093
|
] }),
|
|
6950
|
-
viewState.kind === "loading" && /* @__PURE__ */ (0,
|
|
6951
|
-
/* @__PURE__ */ (0,
|
|
6952
|
-
/* @__PURE__ */ (0,
|
|
7094
|
+
viewState.kind === "loading" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Box19.default, { sx: { minHeight: 120 }, children: [
|
|
7095
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton7.default, { variant: "text", width: "60%", height: 20, sx: { mb: 1 } }),
|
|
7096
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Skeleton7.default, { variant: "rectangular", width: "100%", height: 100 })
|
|
6953
7097
|
] }),
|
|
6954
|
-
viewState.kind === "error" && /* @__PURE__ */ (0,
|
|
6955
|
-
viewState.kind === "unprovisioned" && /* @__PURE__ */ (0,
|
|
6956
|
-
viewState.kind === "ready" && partialFailure && /* @__PURE__ */ (0,
|
|
6957
|
-
viewState.kind === "ready" && /* @__PURE__ */ (0,
|
|
6958
|
-
/* @__PURE__ */ (0,
|
|
6959
|
-
|
|
7098
|
+
viewState.kind === "error" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: viewState.message }),
|
|
7099
|
+
viewState.kind === "unprovisioned" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: UNPROVISIONED_MSG }),
|
|
7100
|
+
viewState.kind === "ready" && partialFailure && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Box19.default, { sx: { mt: 1, mb: 1, p: 1, backgroundColor: "action.hover", borderRadius: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "body2", color: "text.secondary", children: USAGE_UNAVAILABLE_MSG }) }),
|
|
7101
|
+
viewState.kind === "ready" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
7102
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7103
|
+
import_Typography17.default,
|
|
6960
7104
|
{
|
|
6961
7105
|
variant: "body2",
|
|
6962
7106
|
sx: {
|
|
@@ -6967,18 +7111,18 @@ var LiteLLMHomeWidget = ({
|
|
|
6967
7111
|
children: viewState.usageUnavailable ? USAGE_UNAVAILABLE_MSG : usageSummary(usage)
|
|
6968
7112
|
}
|
|
6969
7113
|
),
|
|
6970
|
-
hasSparkline && !viewState.usageUnavailable && /* @__PURE__ */ (0,
|
|
6971
|
-
/* @__PURE__ */ (0,
|
|
6972
|
-
|
|
7114
|
+
hasSparkline && !viewState.usageUnavailable && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
7115
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7116
|
+
import_Box19.default,
|
|
6973
7117
|
{
|
|
6974
7118
|
height: 80,
|
|
6975
7119
|
role: "img",
|
|
6976
7120
|
"aria-label": sparklineAriaLabelText,
|
|
6977
7121
|
sx: { mb: 0.5 },
|
|
6978
|
-
children: /* @__PURE__ */ (0,
|
|
6979
|
-
/* @__PURE__ */ (0,
|
|
6980
|
-
/* @__PURE__ */ (0,
|
|
6981
|
-
/* @__PURE__ */ (0,
|
|
7122
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_recharts3.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_recharts3.AreaChart, { data: dailyData, margin: { top: 4, right: 0, bottom: 0, left: 0 }, children: [
|
|
7123
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_recharts3.XAxis, { dataKey: "date", hide: true }),
|
|
7124
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_recharts3.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ChartTooltip, { valueFormatter: fmtUsd }) }),
|
|
7125
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6982
7126
|
import_recharts3.Area,
|
|
6983
7127
|
{
|
|
6984
7128
|
type: "monotone",
|
|
@@ -6994,13 +7138,13 @@ var LiteLLMHomeWidget = ({
|
|
|
6994
7138
|
] }) })
|
|
6995
7139
|
}
|
|
6996
7140
|
),
|
|
6997
|
-
/* @__PURE__ */ (0,
|
|
7141
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_Typography17.default, { variant: "caption", color: "text.secondary", sx: { display: "block", mb: 1 }, children: [
|
|
6998
7142
|
"daily spend (",
|
|
6999
7143
|
dateRangeCaption,
|
|
7000
7144
|
")"
|
|
7001
7145
|
] })
|
|
7002
7146
|
] }),
|
|
7003
|
-
moduleRouteRef?.() && /* @__PURE__ */ (0,
|
|
7147
|
+
moduleRouteRef?.() && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_Typography17.default, { variant: "caption", sx: { mt: 1, display: "block" }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_core_components5.Link, { to: moduleRouteRef(), color: "primary", children: "Open LiteLLM \u2192" }) })
|
|
7004
7148
|
] })
|
|
7005
7149
|
] });
|
|
7006
7150
|
};
|
|
@@ -7009,20 +7153,20 @@ var LiteLLMHomeWidget = ({
|
|
|
7009
7153
|
init_LiteLLMBudgetWidget();
|
|
7010
7154
|
|
|
7011
7155
|
// src/components/LiteLLMBudgetGauges.tsx
|
|
7012
|
-
var
|
|
7156
|
+
var import_react16 = require("react");
|
|
7013
7157
|
var import_frontend_plugin_api6 = require("@backstage/frontend-plugin-api");
|
|
7014
|
-
var
|
|
7015
|
-
var
|
|
7016
|
-
var
|
|
7017
|
-
var
|
|
7158
|
+
var import_Paper11 = __toESM(require("@mui/material/Paper"));
|
|
7159
|
+
var import_Box20 = __toESM(require("@mui/material/Box"));
|
|
7160
|
+
var import_Button9 = __toESM(require("@mui/material/Button"));
|
|
7161
|
+
var import_Typography18 = __toESM(require("@mui/material/Typography"));
|
|
7018
7162
|
var import_Skeleton8 = __toESM(require("@mui/material/Skeleton"));
|
|
7019
7163
|
var import_Collapse4 = __toESM(require("@mui/material/Collapse"));
|
|
7020
7164
|
var import_styles13 = require("@mui/material/styles");
|
|
7021
7165
|
var import_useMediaQuery = __toESM(require("@mui/material/useMediaQuery"));
|
|
7022
7166
|
var import_icons_material11 = require("@mui/icons-material");
|
|
7023
7167
|
var import_recharts4 = require("recharts");
|
|
7024
|
-
var
|
|
7025
|
-
var
|
|
7168
|
+
var import_core_plugin_api8 = require("@backstage/core-plugin-api");
|
|
7169
|
+
var import_core_components6 = require("@backstage/core-components");
|
|
7026
7170
|
init_useLiteLLMProfile();
|
|
7027
7171
|
init_api();
|
|
7028
7172
|
init_format();
|
|
@@ -7053,7 +7197,7 @@ init_GenerateKeyButton();
|
|
|
7053
7197
|
init_BudgetLimitList();
|
|
7054
7198
|
init_budget();
|
|
7055
7199
|
init_routes();
|
|
7056
|
-
var
|
|
7200
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
7057
7201
|
var LEVEL = {
|
|
7058
7202
|
key: { name: "Key", none: "No cap (unlimited)" },
|
|
7059
7203
|
user: { name: "User", none: "No personal budget" },
|
|
@@ -7077,8 +7221,8 @@ function resetLabel(limit) {
|
|
|
7077
7221
|
const window2 = fmtBudgetDuration(limit.budgetDuration);
|
|
7078
7222
|
return window2 ? `resets ${window2}` : "never resets";
|
|
7079
7223
|
}
|
|
7080
|
-
var Tag = ({ children, tone, title }) => /* @__PURE__ */ (0,
|
|
7081
|
-
|
|
7224
|
+
var Tag = ({ children, tone, title }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7225
|
+
import_Typography18.default,
|
|
7082
7226
|
{
|
|
7083
7227
|
title,
|
|
7084
7228
|
sx: (theme) => ({
|
|
@@ -7095,10 +7239,10 @@ var Tag = ({ children, tone, title }) => /* @__PURE__ */ (0, import_jsx_runtime2
|
|
|
7095
7239
|
children
|
|
7096
7240
|
}
|
|
7097
7241
|
);
|
|
7098
|
-
var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE__ */ (0,
|
|
7099
|
-
/* @__PURE__ */ (0,
|
|
7100
|
-
/* @__PURE__ */ (0,
|
|
7101
|
-
|
|
7242
|
+
var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { sx: { minWidth: 0, flex: 1 }, children: [
|
|
7243
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { sx: { display: "flex", alignItems: "center", gap: 0.625, minWidth: 0 }, children: [
|
|
7244
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7245
|
+
import_Box20.default,
|
|
7102
7246
|
{
|
|
7103
7247
|
sx: (theme) => ({
|
|
7104
7248
|
width: 6,
|
|
@@ -7109,10 +7253,10 @@ var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE_
|
|
|
7109
7253
|
})
|
|
7110
7254
|
}
|
|
7111
7255
|
),
|
|
7112
|
-
/* @__PURE__ */ (0,
|
|
7256
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Tag, { children: label })
|
|
7113
7257
|
] }),
|
|
7114
|
-
/* @__PURE__ */ (0,
|
|
7115
|
-
|
|
7258
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7259
|
+
import_Typography18.default,
|
|
7116
7260
|
{
|
|
7117
7261
|
title,
|
|
7118
7262
|
sx: {
|
|
@@ -7128,8 +7272,8 @@ var InlineStat = ({ label, value, hint, tone = "accent", title }) => /* @__PURE_
|
|
|
7128
7272
|
children: value
|
|
7129
7273
|
}
|
|
7130
7274
|
),
|
|
7131
|
-
/* @__PURE__ */ (0,
|
|
7132
|
-
|
|
7275
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7276
|
+
import_Typography18.default,
|
|
7133
7277
|
{
|
|
7134
7278
|
variant: "caption",
|
|
7135
7279
|
color: "text.secondary",
|
|
@@ -7159,10 +7303,10 @@ var LevelRow = ({
|
|
|
7159
7303
|
const subNote = () => {
|
|
7160
7304
|
if (overCap) return "Over cap";
|
|
7161
7305
|
if (extra > 0 && keysHref) {
|
|
7162
|
-
return /* @__PURE__ */ (0,
|
|
7163
|
-
|
|
7306
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
7307
|
+
import_Typography18.default,
|
|
7164
7308
|
{
|
|
7165
|
-
component:
|
|
7309
|
+
component: import_core_components6.Link,
|
|
7166
7310
|
to: keysHref,
|
|
7167
7311
|
variant: "caption",
|
|
7168
7312
|
sx: {
|
|
@@ -7182,8 +7326,8 @@ var LevelRow = ({
|
|
|
7182
7326
|
return limit?.sublabel ?? null;
|
|
7183
7327
|
};
|
|
7184
7328
|
const gaugeAriaLabel = limit ? `${name} budget used: ${Math.round(limit.pct)}%` : `${name} \u2014 no cap`;
|
|
7185
|
-
return /* @__PURE__ */ (0,
|
|
7186
|
-
|
|
7329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
7330
|
+
import_Box20.default,
|
|
7187
7331
|
{
|
|
7188
7332
|
sx: {
|
|
7189
7333
|
display: "grid",
|
|
@@ -7194,7 +7338,7 @@ var LevelRow = ({
|
|
|
7194
7338
|
minWidth: 0
|
|
7195
7339
|
},
|
|
7196
7340
|
children: [
|
|
7197
|
-
/* @__PURE__ */ (0,
|
|
7341
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7198
7342
|
Gauge,
|
|
7199
7343
|
{
|
|
7200
7344
|
value: limit?.pct ?? 0,
|
|
@@ -7204,11 +7348,11 @@ var LevelRow = ({
|
|
|
7204
7348
|
ariaLabel: gaugeAriaLabel
|
|
7205
7349
|
}
|
|
7206
7350
|
),
|
|
7207
|
-
/* @__PURE__ */ (0,
|
|
7208
|
-
/* @__PURE__ */ (0,
|
|
7209
|
-
limit ? /* @__PURE__ */ (0,
|
|
7210
|
-
/* @__PURE__ */ (0,
|
|
7211
|
-
|
|
7351
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { sx: { minWidth: 0 }, children: [
|
|
7352
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Tag, { tone: tone === "warning" || tone === "danger" ? tone : void 0, children: name }),
|
|
7353
|
+
limit ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
7354
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7355
|
+
import_Typography18.default,
|
|
7212
7356
|
{
|
|
7213
7357
|
variant: "caption",
|
|
7214
7358
|
title: limit.sublabel ? `${limit.label} \xB7 ${limit.sublabel}` : limit.label,
|
|
@@ -7224,8 +7368,8 @@ var LevelRow = ({
|
|
|
7224
7368
|
children: limit.label
|
|
7225
7369
|
}
|
|
7226
7370
|
),
|
|
7227
|
-
/* @__PURE__ */ (0,
|
|
7228
|
-
|
|
7371
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7372
|
+
import_Typography18.default,
|
|
7229
7373
|
{
|
|
7230
7374
|
variant: "caption",
|
|
7231
7375
|
color: overCap ? "error" : "text.secondary",
|
|
@@ -7241,8 +7385,8 @@ var LevelRow = ({
|
|
|
7241
7385
|
children: subNote()
|
|
7242
7386
|
}
|
|
7243
7387
|
)
|
|
7244
|
-
] }) : /* @__PURE__ */ (0,
|
|
7245
|
-
|
|
7388
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7389
|
+
import_Typography18.default,
|
|
7246
7390
|
{
|
|
7247
7391
|
variant: "caption",
|
|
7248
7392
|
color: "text.secondary",
|
|
@@ -7258,9 +7402,9 @@ var LevelRow = ({
|
|
|
7258
7402
|
}
|
|
7259
7403
|
)
|
|
7260
7404
|
] }),
|
|
7261
|
-
/* @__PURE__ */ (0,
|
|
7262
|
-
/* @__PURE__ */ (0,
|
|
7263
|
-
|
|
7405
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { sx: { minWidth: 0, textAlign: "right" }, children: [
|
|
7406
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7407
|
+
import_Typography18.default,
|
|
7264
7408
|
{
|
|
7265
7409
|
title: limit ? `${fmtUsd(limit.spend)} of ${fmtUsd(limit.budget)}` : void 0,
|
|
7266
7410
|
sx: {
|
|
@@ -7277,8 +7421,8 @@ var LevelRow = ({
|
|
|
7277
7421
|
children: amountCaption(limit)
|
|
7278
7422
|
}
|
|
7279
7423
|
),
|
|
7280
|
-
/* @__PURE__ */ (0,
|
|
7281
|
-
|
|
7424
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7425
|
+
import_Typography18.default,
|
|
7282
7426
|
{
|
|
7283
7427
|
variant: "caption",
|
|
7284
7428
|
color: "text.secondary",
|
|
@@ -7309,11 +7453,11 @@ function amountNote(limit) {
|
|
|
7309
7453
|
var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, maxBudget }) => {
|
|
7310
7454
|
const renderPlot = () => {
|
|
7311
7455
|
if (loading) {
|
|
7312
|
-
return /* @__PURE__ */ (0,
|
|
7456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Skeleton8.default, { variant: "rectangular", width: "100%", height: "100%" });
|
|
7313
7457
|
}
|
|
7314
7458
|
if (data.length === 0) {
|
|
7315
|
-
return /* @__PURE__ */ (0,
|
|
7316
|
-
|
|
7459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7460
|
+
import_Box20.default,
|
|
7317
7461
|
{
|
|
7318
7462
|
display: "flex",
|
|
7319
7463
|
justifyContent: "center",
|
|
@@ -7324,10 +7468,10 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
|
|
|
7324
7468
|
}
|
|
7325
7469
|
);
|
|
7326
7470
|
}
|
|
7327
|
-
return /* @__PURE__ */ (0,
|
|
7328
|
-
/* @__PURE__ */ (0,
|
|
7329
|
-
/* @__PURE__ */ (0,
|
|
7330
|
-
maxBudget !== void 0 && /* @__PURE__ */ (0,
|
|
7471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_recharts4.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_recharts4.AreaChart, { data, margin: { top: 4, right: 0, bottom: 0, left: 0 }, children: [
|
|
7472
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_recharts4.XAxis, { dataKey: "date", hide: true }),
|
|
7473
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_recharts4.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ChartTooltip, { valueFormatter: fmtUsd }) }),
|
|
7474
|
+
maxBudget !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7331
7475
|
import_recharts4.ReferenceLine,
|
|
7332
7476
|
{
|
|
7333
7477
|
y: maxBudget,
|
|
@@ -7336,7 +7480,7 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
|
|
|
7336
7480
|
strokeWidth: 1
|
|
7337
7481
|
}
|
|
7338
7482
|
),
|
|
7339
|
-
/* @__PURE__ */ (0,
|
|
7483
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7340
7484
|
import_recharts4.Area,
|
|
7341
7485
|
{
|
|
7342
7486
|
type: "monotone",
|
|
@@ -7358,10 +7502,10 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
|
|
|
7358
7502
|
if (data.length === 0) return "No spend this month";
|
|
7359
7503
|
return mtdCaption();
|
|
7360
7504
|
})();
|
|
7361
|
-
return /* @__PURE__ */ (0,
|
|
7362
|
-
/* @__PURE__ */ (0,
|
|
7363
|
-
/* @__PURE__ */ (0,
|
|
7364
|
-
|
|
7505
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { role: "img", "aria-label": sparklineAriaLabel(data), sx: { minWidth: 0 }, children: [
|
|
7506
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Box20.default, { sx: { height, width: "100%" }, children: renderPlot() }),
|
|
7507
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
7508
|
+
import_Box20.default,
|
|
7365
7509
|
{
|
|
7366
7510
|
sx: {
|
|
7367
7511
|
display: "flex",
|
|
@@ -7372,10 +7516,10 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
|
|
|
7372
7516
|
minWidth: 0
|
|
7373
7517
|
},
|
|
7374
7518
|
children: [
|
|
7375
|
-
/* @__PURE__ */ (0,
|
|
7376
|
-
/* @__PURE__ */ (0,
|
|
7377
|
-
/* @__PURE__ */ (0,
|
|
7378
|
-
|
|
7519
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { sx: { display: "flex", alignItems: "baseline", gap: 0.75, minWidth: 0 }, children: [
|
|
7520
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Tag, { children: "Spent (mtd)" }),
|
|
7521
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7522
|
+
import_Typography18.default,
|
|
7379
7523
|
{
|
|
7380
7524
|
variant: "caption",
|
|
7381
7525
|
color: "text.secondary",
|
|
@@ -7384,8 +7528,8 @@ var SpendStrip = ({ data, mtdSpend, loading, height, usageUnavailable = false, m
|
|
|
7384
7528
|
}
|
|
7385
7529
|
)
|
|
7386
7530
|
] }),
|
|
7387
|
-
/* @__PURE__ */ (0,
|
|
7388
|
-
|
|
7531
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7532
|
+
import_Typography18.default,
|
|
7389
7533
|
{
|
|
7390
7534
|
title: loading || usageUnavailable ? void 0 : `${fmtUsd(mtdSpend)} spent month to date`,
|
|
7391
7535
|
sx: {
|
|
@@ -7429,33 +7573,33 @@ var LiteLLMBudgetGauges = ({
|
|
|
7429
7573
|
teams: propTeams,
|
|
7430
7574
|
keys: propKeys
|
|
7431
7575
|
}) => {
|
|
7432
|
-
const api = (0,
|
|
7576
|
+
const api = (0, import_core_plugin_api8.useApi)(liteLlmApiRef);
|
|
7433
7577
|
const theme = (0, import_styles13.useTheme)();
|
|
7434
7578
|
const isSmallScreen = (0, import_useMediaQuery.default)(theme.breakpoints.down("sm"));
|
|
7435
7579
|
const gaugeSize = isSmallScreen ? Math.min(48, size) : size;
|
|
7436
|
-
const expandedRegionId = (0,
|
|
7580
|
+
const expandedRegionId = (0, import_react16.useId)();
|
|
7437
7581
|
const moduleRouteRef = (0, import_frontend_plugin_api6.useRouteRef)(rootRouteRef);
|
|
7438
7582
|
const moduleHref = propModuleHref ?? moduleRouteRef?.();
|
|
7439
7583
|
const { userInfo: hookUserInfo, teams: hookTeams, keys: hookKeys, loading: profileLoading, error: profileError } = useLiteLLMProfile();
|
|
7440
|
-
const [usageLoading, setUsageLoading] = (0,
|
|
7441
|
-
const [usageError, setUsageError] = (0,
|
|
7442
|
-
const [dailySpend, setDailySpend] = (0,
|
|
7443
|
-
const [mtdSpend, setMtdSpend] = (0,
|
|
7584
|
+
const [usageLoading, setUsageLoading] = (0, import_react16.useState)(true);
|
|
7585
|
+
const [usageError, setUsageError] = (0, import_react16.useState)(null);
|
|
7586
|
+
const [dailySpend, setDailySpend] = (0, import_react16.useState)([]);
|
|
7587
|
+
const [mtdSpend, setMtdSpend] = (0, import_react16.useState)(0);
|
|
7444
7588
|
const user = propUserInfo !== void 0 ? propUserInfo : hookUserInfo;
|
|
7445
7589
|
const teams = propTeams !== void 0 ? propTeams : hookTeams;
|
|
7446
7590
|
const keys = propKeys !== void 0 ? propKeys : hookKeys;
|
|
7447
7591
|
const loading = propUserInfo === void 0 ? profileLoading : usageLoading;
|
|
7448
7592
|
const error = propUserInfo === void 0 ? profileError : usageError;
|
|
7449
7593
|
const isControlled = expanded !== void 0;
|
|
7450
|
-
const [uncontrolledExpanded, setUncontrolledExpanded] = (0,
|
|
7594
|
+
const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react16.useState)(defaultExpanded);
|
|
7451
7595
|
const isExpanded = isControlled ? expanded : uncontrolledExpanded;
|
|
7452
|
-
const toggleExpanded = (0,
|
|
7596
|
+
const toggleExpanded = (0, import_react16.useCallback)(() => {
|
|
7453
7597
|
const next = !isExpanded;
|
|
7454
7598
|
if (!isControlled) setUncontrolledExpanded(next);
|
|
7455
7599
|
onExpandedChange?.(next);
|
|
7456
7600
|
}, [isControlled, isExpanded, onExpandedChange]);
|
|
7457
7601
|
const keysTabHref = keysHref ?? (moduleHref ? `${moduleHref}?tab=keys` : void 0);
|
|
7458
|
-
(0,
|
|
7602
|
+
(0, import_react16.useEffect)(() => {
|
|
7459
7603
|
let cancelled = false;
|
|
7460
7604
|
setUsageLoading(true);
|
|
7461
7605
|
setUsageError(null);
|
|
@@ -7483,21 +7627,21 @@ var LiteLLMBudgetGauges = ({
|
|
|
7483
7627
|
cancelled = true;
|
|
7484
7628
|
};
|
|
7485
7629
|
}, [api]);
|
|
7486
|
-
const summary = (0,
|
|
7630
|
+
const summary = (0, import_react16.useMemo)(
|
|
7487
7631
|
() => buildBudgetSummary(user, teams, keys, keys.length),
|
|
7488
7632
|
[user, teams, keys]
|
|
7489
7633
|
);
|
|
7490
|
-
const gauges = (0,
|
|
7491
|
-
const headline = (0,
|
|
7492
|
-
const expandedSummary = (0,
|
|
7634
|
+
const gauges = (0, import_react16.useMemo)(() => buildBudgetGauges(summary), [summary]);
|
|
7635
|
+
const headline = (0, import_react16.useMemo)(() => budgetHeadline(summary), [summary]);
|
|
7636
|
+
const expandedSummary = (0, import_react16.useMemo)(
|
|
7493
7637
|
() => buildBudgetSummary(user, teams, keys, maxExpandedKeys),
|
|
7494
7638
|
[user, teams, keys, maxExpandedKeys]
|
|
7495
7639
|
);
|
|
7496
|
-
const expandedLimits = (0,
|
|
7640
|
+
const expandedLimits = (0, import_react16.useMemo)(
|
|
7497
7641
|
() => allBudgetLimits(expandedSummary),
|
|
7498
7642
|
[expandedSummary]
|
|
7499
7643
|
);
|
|
7500
|
-
const viewState = (0,
|
|
7644
|
+
const viewState = (0, import_react16.useMemo)(
|
|
7501
7645
|
() => widgetViewState({
|
|
7502
7646
|
loading,
|
|
7503
7647
|
error: profileError,
|
|
@@ -7514,7 +7658,7 @@ var LiteLLMBudgetGauges = ({
|
|
|
7514
7658
|
const yesterdaySpend = dailySpend.some((d) => d.date === toLocalDay(yesterday)) ? spendOnDay(dailySpend, yesterday) : null;
|
|
7515
7659
|
const todayHint = yesterdaySpend === null ? void 0 : `vs ${fmtUsd(yesterdaySpend)} yesterday`;
|
|
7516
7660
|
const summaryText = headline.count === 0 ? "no limits apply" : `${headline.count} limit${headline.count === 1 ? "" : "s"}`;
|
|
7517
|
-
const resolvedCtas = (0,
|
|
7661
|
+
const resolvedCtas = (0, import_react16.useMemo)(() => {
|
|
7518
7662
|
return resolveCtas({
|
|
7519
7663
|
ctas,
|
|
7520
7664
|
hasKeys: (keys?.length ?? 0) > 0,
|
|
@@ -7528,20 +7672,20 @@ var LiteLLMBudgetGauges = ({
|
|
|
7528
7672
|
switch (cta.kind) {
|
|
7529
7673
|
case "new-key":
|
|
7530
7674
|
if (!onCreateKey && !moduleHref) return null;
|
|
7531
|
-
return onCreateKey ? /* @__PURE__ */ (0,
|
|
7675
|
+
return onCreateKey ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GenerateKeyButton, { size: "small", label, onClick: onCreateKey }, key) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GenerateKeyButton, { size: "small", label, to: `${moduleHref}?generate=1` }, key);
|
|
7532
7676
|
case "module":
|
|
7533
7677
|
if (!moduleHref) return null;
|
|
7534
|
-
return /* @__PURE__ */ (0,
|
|
7678
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Button9.default, { size: "small", variant: "text", component: import_core_components6.Link, to: moduleHref, children: label }, key);
|
|
7535
7679
|
case "all-limits":
|
|
7536
|
-
return /* @__PURE__ */ (0,
|
|
7537
|
-
|
|
7680
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7681
|
+
import_Button9.default,
|
|
7538
7682
|
{
|
|
7539
7683
|
size: "small",
|
|
7540
7684
|
variant: "text",
|
|
7541
7685
|
onClick: toggleExpanded,
|
|
7542
7686
|
"aria-expanded": isExpanded,
|
|
7543
7687
|
"aria-controls": expandedRegionId,
|
|
7544
|
-
endIcon: /* @__PURE__ */ (0,
|
|
7688
|
+
endIcon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7545
7689
|
import_icons_material11.ExpandMore,
|
|
7546
7690
|
{
|
|
7547
7691
|
sx: (muiTheme) => ({
|
|
@@ -7560,11 +7704,11 @@ var LiteLLMBudgetGauges = ({
|
|
|
7560
7704
|
}
|
|
7561
7705
|
};
|
|
7562
7706
|
const hasFooter = resolvedCtas.length > 0 || !!action;
|
|
7563
|
-
const Wrapper = bare ?
|
|
7564
|
-
return /* @__PURE__ */ (0,
|
|
7565
|
-
/* @__PURE__ */ (0,
|
|
7566
|
-
!bare && /* @__PURE__ */ (0,
|
|
7567
|
-
!loading && !error && /* @__PURE__ */ (0,
|
|
7707
|
+
const Wrapper = bare ? import_Box20.default : import_Paper11.default;
|
|
7708
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Wrapper, { sx: bare ? { height: "100%" } : { p: 2, height: "100%" }, children: [
|
|
7709
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { sx: { display: "flex", alignItems: "center", gap: 1, mb: 1.5, minWidth: 0, justifyContent: bare ? "flex-end" : void 0 }, children: [
|
|
7710
|
+
!bare && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Typography18.default, { variant: "h6", lineHeight: 1.2, sx: { minWidth: 0, flex: 1 }, children: title }),
|
|
7711
|
+
!loading && !error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7568
7712
|
StatusPill,
|
|
7569
7713
|
{
|
|
7570
7714
|
label: summaryText,
|
|
@@ -7573,19 +7717,19 @@ var LiteLLMBudgetGauges = ({
|
|
|
7573
7717
|
}
|
|
7574
7718
|
)
|
|
7575
7719
|
] }),
|
|
7576
|
-
viewState.kind === "loading" && /* @__PURE__ */ (0,
|
|
7577
|
-
/* @__PURE__ */ (0,
|
|
7578
|
-
/* @__PURE__ */ (0,
|
|
7579
|
-
/* @__PURE__ */ (0,
|
|
7580
|
-
/* @__PURE__ */ (0,
|
|
7720
|
+
viewState.kind === "loading" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Box20.default, { sx: { display: "flex", flexDirection: "column", gap: 1.25, minHeight: size }, children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { sx: { display: "flex", alignItems: "center", gap: 1.25 }, children: [
|
|
7721
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Skeleton8.default, { variant: "circular", width: size, height: size }),
|
|
7722
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_Box20.default, { sx: { flex: 1 }, children: [
|
|
7723
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Skeleton8.default, { variant: "text", width: "70%", height: 12, sx: { mb: 0.25 } }),
|
|
7724
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Skeleton8.default, { variant: "text", width: "45%", height: 11 })
|
|
7581
7725
|
] }),
|
|
7582
|
-
/* @__PURE__ */ (0,
|
|
7726
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Skeleton8.default, { variant: "text", width: 64, height: 12 })
|
|
7583
7727
|
] }, i)) }),
|
|
7584
|
-
viewState.kind === "error" && /* @__PURE__ */ (0,
|
|
7585
|
-
viewState.kind === "unprovisioned" && /* @__PURE__ */ (0,
|
|
7586
|
-
viewState.kind === "ready" && /* @__PURE__ */ (0,
|
|
7587
|
-
/* @__PURE__ */ (0,
|
|
7588
|
-
|
|
7728
|
+
viewState.kind === "error" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Typography18.default, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: viewState.message }),
|
|
7729
|
+
viewState.kind === "unprovisioned" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Typography18.default, { variant: "body2", color: "text.secondary", sx: { mt: 0.5 }, children: UNPROVISIONED_MSG }),
|
|
7730
|
+
viewState.kind === "ready" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
7731
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
7732
|
+
import_Box20.default,
|
|
7589
7733
|
{
|
|
7590
7734
|
sx: {
|
|
7591
7735
|
display: "flex",
|
|
@@ -7595,7 +7739,7 @@ var LiteLLMBudgetGauges = ({
|
|
|
7595
7739
|
minWidth: 0
|
|
7596
7740
|
},
|
|
7597
7741
|
children: [
|
|
7598
|
-
/* @__PURE__ */ (0,
|
|
7742
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7599
7743
|
InlineStat,
|
|
7600
7744
|
{
|
|
7601
7745
|
label: "Today spent",
|
|
@@ -7605,8 +7749,8 @@ var LiteLLMBudgetGauges = ({
|
|
|
7605
7749
|
title: usageLoading || viewState.usageUnavailable ? void 0 : "Spend since local midnight"
|
|
7606
7750
|
}
|
|
7607
7751
|
),
|
|
7608
|
-
/* @__PURE__ */ (0,
|
|
7609
|
-
/* @__PURE__ */ (0,
|
|
7752
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Box20.default, { sx: { width: "1px", bgcolor: "divider", flexShrink: 0 } }),
|
|
7753
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7610
7754
|
InlineStat,
|
|
7611
7755
|
{
|
|
7612
7756
|
label: "Month to date",
|
|
@@ -7618,15 +7762,15 @@ var LiteLLMBudgetGauges = ({
|
|
|
7618
7762
|
]
|
|
7619
7763
|
}
|
|
7620
7764
|
),
|
|
7621
|
-
/* @__PURE__ */ (0,
|
|
7622
|
-
|
|
7765
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Box20.default, { sx: { borderTop: "1px solid", borderColor: "divider" }, children: gauges.map((gauge, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7766
|
+
import_Box20.default,
|
|
7623
7767
|
{
|
|
7624
7768
|
sx: i === 0 ? void 0 : { borderTop: "1px solid", borderColor: "divider" },
|
|
7625
|
-
children: /* @__PURE__ */ (0,
|
|
7769
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(LevelRow, { gauge, size: gaugeSize, keysHref: keysTabHref })
|
|
7626
7770
|
},
|
|
7627
7771
|
gauge.kind
|
|
7628
7772
|
)) }),
|
|
7629
|
-
/* @__PURE__ */ (0,
|
|
7773
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Box20.default, { sx: { mt: 1.25 }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7630
7774
|
SpendStrip,
|
|
7631
7775
|
{
|
|
7632
7776
|
data: dailySpend,
|
|
@@ -7637,8 +7781,8 @@ var LiteLLMBudgetGauges = ({
|
|
|
7637
7781
|
maxBudget: user?.max_budget ?? void 0
|
|
7638
7782
|
}
|
|
7639
7783
|
) }),
|
|
7640
|
-
/* @__PURE__ */ (0,
|
|
7641
|
-
|
|
7784
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_Collapse4.default, { in: isExpanded, unmountOnExit: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7785
|
+
import_Box20.default,
|
|
7642
7786
|
{
|
|
7643
7787
|
id: expandedRegionId,
|
|
7644
7788
|
sx: {
|
|
@@ -7648,7 +7792,7 @@ var LiteLLMBudgetGauges = ({
|
|
|
7648
7792
|
maxHeight: 300,
|
|
7649
7793
|
overflowY: "auto"
|
|
7650
7794
|
},
|
|
7651
|
-
children: /* @__PURE__ */ (0,
|
|
7795
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(LimitListPanel, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7652
7796
|
BudgetLimitList,
|
|
7653
7797
|
{
|
|
7654
7798
|
limits: expandedLimits,
|
|
@@ -7659,8 +7803,8 @@ var LiteLLMBudgetGauges = ({
|
|
|
7659
7803
|
}
|
|
7660
7804
|
) })
|
|
7661
7805
|
] }),
|
|
7662
|
-
hasFooter && /* @__PURE__ */ (0,
|
|
7663
|
-
|
|
7806
|
+
hasFooter && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
7807
|
+
import_Box20.default,
|
|
7664
7808
|
{
|
|
7665
7809
|
sx: (muiTheme) => ({
|
|
7666
7810
|
mt: 2,
|