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