@acarmisc/backstage-plugin-litellm 0.45.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 +6 -3
- package/dist/index.cjs.js +105 -43
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.esm.js +105 -43
- 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,
|
|
@@ -5084,53 +5086,92 @@ function budgetStatValue(hidden, budget) {
|
|
|
5084
5086
|
if (budget > 0) return fmtUsd2(budget);
|
|
5085
5087
|
return "Unlimited";
|
|
5086
5088
|
}
|
|
5087
|
-
var fmtUsd2, monoSx,
|
|
5089
|
+
var fmtUsd2, monoSx, fmtShare, MemberUsageCards, TeamKeyUsageTable, TeamCard, TeamUsage;
|
|
5088
5090
|
var init_TeamUsage = __esm({
|
|
5089
5091
|
"src/components/TeamUsage.tsx"() {
|
|
5090
5092
|
"use strict";
|
|
5091
5093
|
init_ui();
|
|
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)}%`;
|
|
5097
|
+
MemberUsageCards = ({ usage, filterText }) => {
|
|
5095
5098
|
const hidden = usage.budget_hidden === true;
|
|
5096
5099
|
if (!usage.members.length) {
|
|
5097
5100
|
return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "No members or activity in this period." });
|
|
5098
5101
|
}
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
/* @__PURE__ */ jsx15(
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
sub
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
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);
|
|
5109
|
+
const people = usage.members.filter((m) => m.user_id !== null).length;
|
|
5110
|
+
return /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
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` }),
|
|
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(
|
|
5113
|
+
Box14,
|
|
5114
|
+
{
|
|
5115
|
+
role: "list",
|
|
5116
|
+
"aria-label": "Usage by member",
|
|
5117
|
+
sx: { display: "grid", gap: 1.5, gridTemplateColumns: "repeat(auto-fill, minmax(230px, 1fr))" },
|
|
5118
|
+
children: visible.map((m) => {
|
|
5119
|
+
const name = m.display_name ?? m.user_email ?? m.user_id;
|
|
5120
|
+
let sub = null;
|
|
5121
|
+
if (m.display_name) sub = m.user_email ?? m.user_id;
|
|
5122
|
+
else if (m.user_email && m.user_id !== m.user_email) sub = m.user_id;
|
|
5123
|
+
const stats = [
|
|
5124
|
+
["Tokens", fmtCompact(m.total_tokens)],
|
|
5125
|
+
["Requests", m.api_requests.toLocaleString()],
|
|
5126
|
+
["Success", m.success_rate === null ? "\u2014" : `${m.success_rate.toFixed(0)}%`],
|
|
5127
|
+
["Keys", m.user_id === null ? "\u2014" : String(m.key_count)]
|
|
5128
|
+
];
|
|
5129
|
+
return /* @__PURE__ */ jsxs14(
|
|
5130
|
+
Paper8,
|
|
5131
|
+
{
|
|
5132
|
+
role: "listitem",
|
|
5133
|
+
variant: "outlined",
|
|
5134
|
+
sx: { borderRadius: 1.5, p: 1.5, minWidth: 0 },
|
|
5135
|
+
children: [
|
|
5136
|
+
/* @__PURE__ */ jsxs14(Box14, { display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 1, children: [
|
|
5137
|
+
/* @__PURE__ */ jsx15(Box14, { minWidth: 0, 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: [
|
|
5138
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "body2", fontWeight: 600, noWrap: true, children: name }),
|
|
5139
|
+
sub && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", noWrap: true, sx: { ...monoSx, display: "block" }, children: sub })
|
|
5140
|
+
] }) }),
|
|
5141
|
+
m.role && /* @__PURE__ */ jsx15(StatusPill, { label: m.role, tone: m.role === "admin" ? "accent" : "neutral", dot: false })
|
|
5142
|
+
] }),
|
|
5143
|
+
/* @__PURE__ */ jsxs14(Box14, { mt: 1.5, display: "flex", alignItems: "baseline", justifyContent: "space-between", children: [
|
|
5144
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "h6", component: "span", sx: { lineHeight: 1.2 }, children: hidden ? fmtShare(m.spend_share_pct) : fmtUsd2(m.spend) }),
|
|
5145
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: hidden ? "of team usage" : `${fmtShare(m.spend_share_pct)} of team` })
|
|
5146
|
+
] }),
|
|
5147
|
+
/* @__PURE__ */ jsx15(Box14, { mt: 0.75, children: /* @__PURE__ */ jsx15(Meter, { value: m.spend_share_pct, ariaLabel: `${name ?? "Unattributed"} share of team spend` }) }),
|
|
5148
|
+
/* @__PURE__ */ jsx15(Box14, { mt: 1.5, display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 0.5, children: stats.map(([label, value]) => /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5149
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", display: "block", children: label }),
|
|
5150
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "body2", children: value })
|
|
5151
|
+
] }, label)) })
|
|
5152
|
+
]
|
|
5153
|
+
},
|
|
5154
|
+
m.user_id ?? "__unattributed"
|
|
5155
|
+
);
|
|
5156
|
+
})
|
|
5157
|
+
}
|
|
5158
|
+
)
|
|
5159
|
+
] });
|
|
5128
5160
|
};
|
|
5129
|
-
TeamKeyUsageTable = ({ usage }) => {
|
|
5161
|
+
TeamKeyUsageTable = ({ usage, filterText }) => {
|
|
5130
5162
|
const hidden = usage.budget_hidden === true;
|
|
5131
5163
|
if (!usage.keys.length) {
|
|
5132
5164
|
return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "This team has no keys." });
|
|
5133
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
|
+
}
|
|
5134
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: [
|
|
5135
5176
|
/* @__PURE__ */ jsx15(TableHead4, { children: /* @__PURE__ */ jsxs14(TableRow4, { children: [
|
|
5136
5177
|
/* @__PURE__ */ jsx15(TableCell4, { children: "Key" }),
|
|
@@ -5142,7 +5183,7 @@ var init_TeamUsage = __esm({
|
|
|
5142
5183
|
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Tokens" }),
|
|
5143
5184
|
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Requests" })
|
|
5144
5185
|
] }) }),
|
|
5145
|
-
/* @__PURE__ */ jsx15(TableBody4, { children:
|
|
5186
|
+
/* @__PURE__ */ jsx15(TableBody4, { children: visible.map((k) => {
|
|
5146
5187
|
const owner = k.display_name ?? k.user_email ?? k.user_id;
|
|
5147
5188
|
return /* @__PURE__ */ jsxs14(TableRow4, { children: [
|
|
5148
5189
|
/* @__PURE__ */ jsxs14(TableCell4, { children: [
|
|
@@ -5168,7 +5209,9 @@ var init_TeamUsage = __esm({
|
|
|
5168
5209
|
};
|
|
5169
5210
|
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, memberUsageFailed, keyUsage, keyUsageLoading, keyUsageFailed, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
|
|
5170
5211
|
const [expanded, setExpanded] = useState9(false);
|
|
5212
|
+
const [teamSearch, setTeamSearch] = useState9("");
|
|
5171
5213
|
const chart = useChartTheme();
|
|
5214
|
+
const searchValue = teamSearch.trim() ? teamSearch : "";
|
|
5172
5215
|
const handleExpandChange = (newExpanded) => {
|
|
5173
5216
|
setExpanded(newExpanded);
|
|
5174
5217
|
if (newExpanded && onExpand) {
|
|
@@ -5366,18 +5409,37 @@ var init_TeamUsage = __esm({
|
|
|
5366
5409
|
renderNamedTags("MCP servers", team.object_permission?.mcp_servers, mcpServers),
|
|
5367
5410
|
renderDailySpendSection(),
|
|
5368
5411
|
(memberUsageLoading || memberUsage || memberUsageFailed) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5369
|
-
|
|
5370
|
-
|
|
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 }),
|
|
5371
5430
|
!memberUsage && memberUsageFailed && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: "Could not load per-member usage" }),
|
|
5372
5431
|
!memberUsage && !memberUsageFailed && /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5373
5432
|
] }),
|
|
5374
5433
|
(keyUsageLoading || keyUsage || keyUsageFailed) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5375
|
-
|
|
5376
|
-
|
|
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 }),
|
|
5377
5439
|
!keyUsage && keyUsageFailed && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: "Could not load per-key usage" }),
|
|
5378
5440
|
!keyUsage && !keyUsageFailed && /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5379
5441
|
] }),
|
|
5380
|
-
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5442
|
+
!memberUsage && /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5381
5443
|
sectionLabel("Members"),
|
|
5382
5444
|
team.members_with_roles?.length ? /* @__PURE__ */ jsx15(
|
|
5383
5445
|
TableContainer4,
|
|
@@ -5535,8 +5597,8 @@ import MenuItem5 from "@mui/material/MenuItem";
|
|
|
5535
5597
|
import Select from "@mui/material/Select";
|
|
5536
5598
|
import FormControl from "@mui/material/FormControl";
|
|
5537
5599
|
import InputLabel from "@mui/material/InputLabel";
|
|
5538
|
-
import
|
|
5539
|
-
import
|
|
5600
|
+
import TextField6 from "@mui/material/TextField";
|
|
5601
|
+
import InputAdornment4 from "@mui/material/InputAdornment";
|
|
5540
5602
|
import { Search as Search2 } from "@mui/icons-material";
|
|
5541
5603
|
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
|
5542
5604
|
import Tooltip7 from "@mui/material/Tooltip";
|
|
@@ -5675,7 +5737,7 @@ var init_ModelsTable = __esm({
|
|
|
5675
5737
|
)
|
|
5676
5738
|
] }),
|
|
5677
5739
|
/* @__PURE__ */ jsx16(
|
|
5678
|
-
|
|
5740
|
+
TextField6,
|
|
5679
5741
|
{
|
|
5680
5742
|
label: "Filter Models",
|
|
5681
5743
|
size: "small",
|
|
@@ -5684,7 +5746,7 @@ var init_ModelsTable = __esm({
|
|
|
5684
5746
|
disabled: !selectedTeamId,
|
|
5685
5747
|
sx: { minWidth: 240, mb: 2 },
|
|
5686
5748
|
InputProps: {
|
|
5687
|
-
startAdornment: /* @__PURE__ */ jsx16(
|
|
5749
|
+
startAdornment: /* @__PURE__ */ jsx16(InputAdornment4, { position: "start", children: /* @__PURE__ */ jsx16(Search2, { fontSize: "small" }) })
|
|
5688
5750
|
}
|
|
5689
5751
|
}
|
|
5690
5752
|
)
|