@acarmisc/backstage-plugin-litellm 0.46.0 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/TeamUsage.d.ts +2 -0
- package/dist/index.cjs.js +54 -15
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.esm.js +53 -14
- package/dist/index.esm.js.map +3 -3
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -5056,10 +5056,12 @@ import TableContainer4 from "@mui/material/TableContainer";
|
|
|
5056
5056
|
import Collapse2 from "@mui/material/Collapse";
|
|
5057
5057
|
import IconButton6 from "@mui/material/IconButton";
|
|
5058
5058
|
import Button6 from "@mui/material/Button";
|
|
5059
|
+
import TextField5 from "@mui/material/TextField";
|
|
5060
|
+
import InputAdornment3 from "@mui/material/InputAdornment";
|
|
5059
5061
|
import CircularProgress4 from "@mui/material/CircularProgress";
|
|
5060
5062
|
import { alpha as alpha10 } from "@mui/material/styles";
|
|
5061
5063
|
import MuiTooltip from "@mui/material/Tooltip";
|
|
5062
|
-
import { ExpandMore as ExpandMore3, Group, Add as Add2, LockOutlined, GroupAddOutlined } from "@mui/icons-material";
|
|
5064
|
+
import { ExpandMore as ExpandMore3, Group, Add as Add2, LockOutlined, GroupAddOutlined, Search as SearchIcon, Close as CloseIcon } from "@mui/icons-material";
|
|
5063
5065
|
import {
|
|
5064
5066
|
AreaChart as AreaChart2,
|
|
5065
5067
|
Area as Area2,
|
|
@@ -5092,21 +5094,28 @@ var init_TeamUsage = __esm({
|
|
|
5092
5094
|
fmtUsd2 = (n) => `$${(n ?? 0).toFixed(2)}`;
|
|
5093
5095
|
monoSx = { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 };
|
|
5094
5096
|
fmtShare = (pct) => `${pct.toFixed(pct > 0 && pct < 1 ? 1 : 0)}%`;
|
|
5095
|
-
MemberUsageCards = ({ usage }) => {
|
|
5097
|
+
MemberUsageCards = ({ usage, filterText }) => {
|
|
5096
5098
|
const hidden = usage.budget_hidden === true;
|
|
5097
5099
|
if (!usage.members.length) {
|
|
5098
5100
|
return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "No members or activity in this period." });
|
|
5099
5101
|
}
|
|
5102
|
+
const query = (filterText ?? "").trim().toLowerCase();
|
|
5103
|
+
const matches = (m) => {
|
|
5104
|
+
if (!query) return true;
|
|
5105
|
+
const haystacks = m.user_id === null ? ["Unattributed"] : [m.display_name, m.user_email, m.user_id];
|
|
5106
|
+
return haystacks.some((h) => h && h.toLowerCase().includes(query));
|
|
5107
|
+
};
|
|
5108
|
+
const visible = usage.members.filter(matches);
|
|
5100
5109
|
const people = usage.members.filter((m) => m.user_id !== null).length;
|
|
5101
5110
|
return /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5102
5111
|
!hidden && people > 0 && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", sx: { display: "block", mb: 1 }, children: `Team spend ${fmtUsd2(usage.total_spend)} \xB7 avg ${fmtUsd2(usage.total_spend / people)} per member` }),
|
|
5103
|
-
/* @__PURE__ */ jsx15(
|
|
5112
|
+
visible.length === 0 ? /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", sx: { display: "block", py: 1 }, children: "No members match that filter." }) : /* @__PURE__ */ jsx15(
|
|
5104
5113
|
Box14,
|
|
5105
5114
|
{
|
|
5106
5115
|
role: "list",
|
|
5107
5116
|
"aria-label": "Usage by member",
|
|
5108
5117
|
sx: { display: "grid", gap: 1.5, gridTemplateColumns: "repeat(auto-fill, minmax(230px, 1fr))" },
|
|
5109
|
-
children:
|
|
5118
|
+
children: visible.map((m) => {
|
|
5110
5119
|
const name = m.display_name ?? m.user_email ?? m.user_id;
|
|
5111
5120
|
let sub = null;
|
|
5112
5121
|
if (m.display_name) sub = m.user_email ?? m.user_id;
|
|
@@ -5149,11 +5158,20 @@ var init_TeamUsage = __esm({
|
|
|
5149
5158
|
)
|
|
5150
5159
|
] });
|
|
5151
5160
|
};
|
|
5152
|
-
TeamKeyUsageTable = ({ usage }) => {
|
|
5161
|
+
TeamKeyUsageTable = ({ usage, filterText }) => {
|
|
5153
5162
|
const hidden = usage.budget_hidden === true;
|
|
5154
5163
|
if (!usage.keys.length) {
|
|
5155
5164
|
return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "This team has no keys." });
|
|
5156
5165
|
}
|
|
5166
|
+
const query = (filterText ?? "").trim().toLowerCase();
|
|
5167
|
+
const visible = usage.keys.filter((k) => {
|
|
5168
|
+
if (!query) return true;
|
|
5169
|
+
const haystacks = [k.key_alias, k.key, k.user_email, k.user_id, k.display_name];
|
|
5170
|
+
return haystacks.some((h) => h && h.toLowerCase().includes(query));
|
|
5171
|
+
});
|
|
5172
|
+
if (visible.length === 0) {
|
|
5173
|
+
return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", sx: { display: "block", py: 1 }, children: "No keys match that filter." });
|
|
5174
|
+
}
|
|
5157
5175
|
return /* @__PURE__ */ jsx15(TableContainer4, { component: Paper8, variant: "outlined", sx: { borderRadius: 1.5 }, children: /* @__PURE__ */ jsxs14(Table4, { size: "small", sx: dataTableSx, "aria-label": "Keys by member", children: [
|
|
5158
5176
|
/* @__PURE__ */ jsx15(TableHead4, { children: /* @__PURE__ */ jsxs14(TableRow4, { children: [
|
|
5159
5177
|
/* @__PURE__ */ jsx15(TableCell4, { children: "Key" }),
|
|
@@ -5165,7 +5183,7 @@ var init_TeamUsage = __esm({
|
|
|
5165
5183
|
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Tokens" }),
|
|
5166
5184
|
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Requests" })
|
|
5167
5185
|
] }) }),
|
|
5168
|
-
/* @__PURE__ */ jsx15(TableBody4, { children:
|
|
5186
|
+
/* @__PURE__ */ jsx15(TableBody4, { children: visible.map((k) => {
|
|
5169
5187
|
const owner = k.display_name ?? k.user_email ?? k.user_id;
|
|
5170
5188
|
return /* @__PURE__ */ jsxs14(TableRow4, { children: [
|
|
5171
5189
|
/* @__PURE__ */ jsxs14(TableCell4, { children: [
|
|
@@ -5191,7 +5209,9 @@ var init_TeamUsage = __esm({
|
|
|
5191
5209
|
};
|
|
5192
5210
|
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, memberUsageFailed, keyUsage, keyUsageLoading, keyUsageFailed, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
|
|
5193
5211
|
const [expanded, setExpanded] = useState9(false);
|
|
5212
|
+
const [teamSearch, setTeamSearch] = useState9("");
|
|
5194
5213
|
const chart = useChartTheme();
|
|
5214
|
+
const searchValue = teamSearch.trim() ? teamSearch : "";
|
|
5195
5215
|
const handleExpandChange = (newExpanded) => {
|
|
5196
5216
|
setExpanded(newExpanded);
|
|
5197
5217
|
if (newExpanded && onExpand) {
|
|
@@ -5389,14 +5409,33 @@ var init_TeamUsage = __esm({
|
|
|
5389
5409
|
renderNamedTags("MCP servers", team.object_permission?.mcp_servers, mcpServers),
|
|
5390
5410
|
renderDailySpendSection(),
|
|
5391
5411
|
(memberUsageLoading || memberUsage || memberUsageFailed) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5392
|
-
|
|
5393
|
-
|
|
5412
|
+
/* @__PURE__ */ jsxs14(Box14, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 1, mb: 1, children: [
|
|
5413
|
+
sectionLabel("Usage by member"),
|
|
5414
|
+
/* @__PURE__ */ jsx15(
|
|
5415
|
+
TextField5,
|
|
5416
|
+
{
|
|
5417
|
+
size: "small",
|
|
5418
|
+
placeholder: "Filter members by name or email\u2026",
|
|
5419
|
+
value: teamSearch,
|
|
5420
|
+
onChange: (e) => setTeamSearch(e.target.value),
|
|
5421
|
+
sx: { width: { xs: "100%", sm: 260 } },
|
|
5422
|
+
InputProps: {
|
|
5423
|
+
startAdornment: /* @__PURE__ */ jsx15(InputAdornment3, { position: "start", children: /* @__PURE__ */ jsx15(SearchIcon, { fontSize: "small", color: "disabled" }) }),
|
|
5424
|
+
endAdornment: searchValue ? /* @__PURE__ */ jsx15(InputAdornment3, { position: "end", children: /* @__PURE__ */ jsx15(IconButton6, { size: "small", onClick: () => setTeamSearch(""), "aria-label": "Clear member filter", children: /* @__PURE__ */ jsx15(CloseIcon, { fontSize: "small" }) }) }) : void 0
|
|
5425
|
+
}
|
|
5426
|
+
}
|
|
5427
|
+
)
|
|
5428
|
+
] }),
|
|
5429
|
+
memberUsage && /* @__PURE__ */ jsx15(MemberUsageCards, { usage: memberUsage, filterText: searchValue }),
|
|
5394
5430
|
!memberUsage && memberUsageFailed && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: "Could not load per-member usage" }),
|
|
5395
5431
|
!memberUsage && !memberUsageFailed && /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5396
5432
|
] }),
|
|
5397
5433
|
(keyUsageLoading || keyUsage || keyUsageFailed) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5398
|
-
|
|
5399
|
-
|
|
5434
|
+
/* @__PURE__ */ jsxs14(Box14, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 1, mb: 1, children: [
|
|
5435
|
+
sectionLabel("Keys by member"),
|
|
5436
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", noWrap: true, children: "Filter member keys, owner or alias" })
|
|
5437
|
+
] }),
|
|
5438
|
+
keyUsage && /* @__PURE__ */ jsx15(TeamKeyUsageTable, { usage: keyUsage, filterText: searchValue }),
|
|
5400
5439
|
!keyUsage && keyUsageFailed && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: "Could not load per-key usage" }),
|
|
5401
5440
|
!keyUsage && !keyUsageFailed && /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5402
5441
|
] }),
|
|
@@ -5558,8 +5597,8 @@ import MenuItem5 from "@mui/material/MenuItem";
|
|
|
5558
5597
|
import Select from "@mui/material/Select";
|
|
5559
5598
|
import FormControl from "@mui/material/FormControl";
|
|
5560
5599
|
import InputLabel from "@mui/material/InputLabel";
|
|
5561
|
-
import
|
|
5562
|
-
import
|
|
5600
|
+
import TextField6 from "@mui/material/TextField";
|
|
5601
|
+
import InputAdornment4 from "@mui/material/InputAdornment";
|
|
5563
5602
|
import { Search as Search2 } from "@mui/icons-material";
|
|
5564
5603
|
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
|
5565
5604
|
import Tooltip7 from "@mui/material/Tooltip";
|
|
@@ -5698,7 +5737,7 @@ var init_ModelsTable = __esm({
|
|
|
5698
5737
|
)
|
|
5699
5738
|
] }),
|
|
5700
5739
|
/* @__PURE__ */ jsx16(
|
|
5701
|
-
|
|
5740
|
+
TextField6,
|
|
5702
5741
|
{
|
|
5703
5742
|
label: "Filter Models",
|
|
5704
5743
|
size: "small",
|
|
@@ -5707,7 +5746,7 @@ var init_ModelsTable = __esm({
|
|
|
5707
5746
|
disabled: !selectedTeamId,
|
|
5708
5747
|
sx: { minWidth: 240, mb: 2 },
|
|
5709
5748
|
InputProps: {
|
|
5710
|
-
startAdornment: /* @__PURE__ */ jsx16(
|
|
5749
|
+
startAdornment: /* @__PURE__ */ jsx16(InputAdornment4, { position: "start", children: /* @__PURE__ */ jsx16(Search2, { fontSize: "small" }) })
|
|
5711
5750
|
}
|
|
5712
5751
|
}
|
|
5713
5752
|
)
|