@acarmisc/backstage-plugin-litellm 0.17.0 → 0.18.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/index.cjs.js CHANGED
@@ -1942,7 +1942,7 @@ var init_GenerateKeyDialog = __esm({
1942
1942
  });
1943
1943
 
1944
1944
  // src/components/ManageTeamDialog.tsx
1945
- var import_react5, import_Dialog3, import_DialogTitle3, import_DialogContent3, import_DialogActions3, import_TextField3, import_Button4, import_Alert2, import_Checkbox2, import_FormControlLabel2, import_Autocomplete3, import_MenuItem2, import_Box5, import_Divider2, import_Typography5, import_IconButton3, import_List, import_ListItem, import_ListItemText, import_icons_material4, BUDGET_DURATION_OPTIONS, DEFAULT_BUDGET_DURATION, FALLBACK_BUDGET_CEILING, ManageTeamDialog;
1945
+ var import_react5, import_Dialog3, import_DialogTitle3, import_DialogContent3, import_DialogActions3, import_TextField3, import_Button4, import_Alert2, import_Checkbox2, import_FormControlLabel2, import_Autocomplete3, import_CircularProgress3, import_MenuItem2, import_Box5, import_Divider2, import_Typography5, import_IconButton3, import_Paper3, import_Table2, import_TableBody2, import_TableCell2, import_TableContainer2, import_TableHead2, import_TableRow2, import_icons_material4, import_core_plugin_api2, import_plugin_catalog_react, import_catalog_model, import_react_use, BUDGET_DURATION_OPTIONS, DEFAULT_BUDGET_DURATION, FALLBACK_BUDGET_CEILING, ManageTeamDialog;
1946
1946
  var init_ManageTeamDialog = __esm({
1947
1947
  "src/components/ManageTeamDialog.tsx"() {
1948
1948
  "use strict";
@@ -1957,15 +1957,25 @@ var init_ManageTeamDialog = __esm({
1957
1957
  import_Checkbox2 = __toESM(require("@mui/material/Checkbox"));
1958
1958
  import_FormControlLabel2 = __toESM(require("@mui/material/FormControlLabel"));
1959
1959
  import_Autocomplete3 = __toESM(require("@mui/material/Autocomplete"));
1960
+ import_CircularProgress3 = __toESM(require("@mui/material/CircularProgress"));
1960
1961
  import_MenuItem2 = __toESM(require("@mui/material/MenuItem"));
1961
1962
  import_Box5 = __toESM(require("@mui/material/Box"));
1962
1963
  import_Divider2 = __toESM(require("@mui/material/Divider"));
1963
1964
  import_Typography5 = __toESM(require("@mui/material/Typography"));
1964
1965
  import_IconButton3 = __toESM(require("@mui/material/IconButton"));
1965
- import_List = __toESM(require("@mui/material/List"));
1966
- import_ListItem = __toESM(require("@mui/material/ListItem"));
1967
- import_ListItemText = __toESM(require("@mui/material/ListItemText"));
1966
+ import_Paper3 = __toESM(require("@mui/material/Paper"));
1967
+ import_Table2 = __toESM(require("@mui/material/Table"));
1968
+ import_TableBody2 = __toESM(require("@mui/material/TableBody"));
1969
+ import_TableCell2 = __toESM(require("@mui/material/TableCell"));
1970
+ import_TableContainer2 = __toESM(require("@mui/material/TableContainer"));
1971
+ import_TableHead2 = __toESM(require("@mui/material/TableHead"));
1972
+ import_TableRow2 = __toESM(require("@mui/material/TableRow"));
1968
1973
  import_icons_material4 = require("@mui/icons-material");
1974
+ import_core_plugin_api2 = require("@backstage/core-plugin-api");
1975
+ import_plugin_catalog_react = require("@backstage/plugin-catalog-react");
1976
+ import_catalog_model = require("@backstage/catalog-model");
1977
+ import_react_use = require("react-use");
1978
+ init_ui();
1969
1979
  BUDGET_DURATION_OPTIONS = [
1970
1980
  { value: "1d", label: "Daily (1d)" },
1971
1981
  { value: "7d", label: "Weekly (7d)" },
@@ -2000,6 +2010,7 @@ var init_ManageTeamDialog = __esm({
2000
2010
  const [budgetDuration, setBudgetDuration] = (0, import_react5.useState)("");
2001
2011
  const [submitting, setSubmitting] = (0, import_react5.useState)(false);
2002
2012
  const [error, setError] = (0, import_react5.useState)(null);
2013
+ const [memberQuery, setMemberQuery] = (0, import_react5.useState)("");
2003
2014
  const [memberRef, setMemberRef] = (0, import_react5.useState)("");
2004
2015
  const [memberBudget, setMemberBudget] = (0, import_react5.useState)("");
2005
2016
  const [memberBusy, setMemberBusy] = (0, import_react5.useState)(false);
@@ -2012,6 +2023,36 @@ var init_ManageTeamDialog = __esm({
2012
2023
  const [mcpError, setMcpError] = (0, import_react5.useState)(null);
2013
2024
  const allowUnlimitedBudget = config?.teamManagement?.allowUnlimitedBudget ?? false;
2014
2025
  const maxBudgetCeiling = config?.teamManagement?.maxBudgetCeiling ?? FALLBACK_BUDGET_CEILING;
2026
+ const members = (0, import_react5.useMemo)(() => team?.members_with_roles ?? [], [team]);
2027
+ const showMembers = mode === "edit" && !!canManageMembers;
2028
+ const catalogApi = (0, import_core_plugin_api2.useApi)(import_plugin_catalog_react.catalogApiRef);
2029
+ const { value: catalogUsers, loading: usersLoading } = (0, import_react_use.useAsync)(async () => {
2030
+ if (!open || !showMembers) return [];
2031
+ try {
2032
+ const { items } = await catalogApi.getEntities({
2033
+ filter: { kind: "User" },
2034
+ fields: ["kind", "metadata.namespace", "metadata.name", "metadata.title", "spec.profile"]
2035
+ });
2036
+ return items;
2037
+ } catch {
2038
+ return [];
2039
+ }
2040
+ }, [open, showMembers, catalogApi]);
2041
+ const userOptions = (0, import_react5.useMemo)(() => {
2042
+ const existingEmails = new Set(
2043
+ members.map((m) => m.user_email?.toLowerCase()).filter((e) => !!e)
2044
+ );
2045
+ return (catalogUsers ?? []).map((e) => {
2046
+ const ref = (0, import_catalog_model.stringifyEntityRef)(e);
2047
+ const displayName = e.spec?.profile?.displayName || e.metadata.title || e.metadata.name;
2048
+ const email = e.spec?.profile?.email;
2049
+ return {
2050
+ ref,
2051
+ email,
2052
+ label: email ? `${displayName} (${email})` : displayName
2053
+ };
2054
+ }).filter((o) => !(o.email && existingEmails.has(o.email.toLowerCase()))).sort((a, b) => a.label.localeCompare(b.label));
2055
+ }, [catalogUsers, members]);
2015
2056
  (0, import_react5.useEffect)(() => {
2016
2057
  if (open) {
2017
2058
  if (mode === "edit" && team) {
@@ -2030,6 +2071,7 @@ var init_ManageTeamDialog = __esm({
2030
2071
  setBudgetDuration(DEFAULT_BUDGET_DURATION);
2031
2072
  }
2032
2073
  setError(null);
2074
+ setMemberQuery("");
2033
2075
  setMemberRef("");
2034
2076
  setMemberBudget("");
2035
2077
  setMemberError(null);
@@ -2101,6 +2143,7 @@ var init_ManageTeamDialog = __esm({
2101
2143
  try {
2102
2144
  setMemberBusy(true);
2103
2145
  await onAddMember(memberRef.trim(), budget);
2146
+ setMemberQuery("");
2104
2147
  setMemberRef("");
2105
2148
  setMemberBudget("");
2106
2149
  } catch (err) {
@@ -2147,8 +2190,6 @@ var init_ManageTeamDialog = __esm({
2147
2190
  };
2148
2191
  const modelNames = allModels.map((m) => m.model_name);
2149
2192
  const durationOptions = BUDGET_DURATION_OPTIONS.some((o) => o.value === budgetDuration) ? BUDGET_DURATION_OPTIONS : [...BUDGET_DURATION_OPTIONS, { value: budgetDuration, label: budgetDuration }];
2150
- const members = team?.members_with_roles ?? [];
2151
- const showMembers = mode === "edit" && !!canManageMembers;
2152
2193
  const showKnowledgeBases = mode === "edit" && !!canManageKnowledgeBases;
2153
2194
  const kbOptions = (vectorStores ?? []).map((v) => v.id);
2154
2195
  const kbLabel = (id) => (vectorStores ?? []).find((v) => v.id === id)?.name ?? id;
@@ -2172,7 +2213,15 @@ var init_ManageTeamDialog = __esm({
2172
2213
  value: models,
2173
2214
  onChange: (_, newValue) => setModels(newValue),
2174
2215
  disabled: submitting,
2175
- renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(import_TextField3.default, { ...params, label: "Models" })
2216
+ renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(
2217
+ import_TextField3.default,
2218
+ {
2219
+ ...params,
2220
+ label: "Models",
2221
+ required: true,
2222
+ helperText: "At least one model is required here \u2014 this delegated flow only grants access to models your admin has allow-listed for team creation, not every proxy model. (Teams with no model restriction shown elsewhere were configured directly in LiteLLM.)"
2223
+ }
2224
+ )
2176
2225
  }
2177
2226
  ), /* @__PURE__ */ import_react5.default.createElement(
2178
2227
  import_TextField3.default,
@@ -2204,34 +2253,69 @@ var init_ManageTeamDialog = __esm({
2204
2253
  fullWidth: true
2205
2254
  },
2206
2255
  durationOptions.map((o) => /* @__PURE__ */ import_react5.default.createElement(import_MenuItem2.default, { key: o.value, value: o.value }, o.label))
2207
- ), showMembers && /* @__PURE__ */ import_react5.default.createElement(import_Box5.default, null, /* @__PURE__ */ import_react5.default.createElement(import_Divider2.default, { sx: { my: 1 } }), /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "subtitle2", sx: { mb: 1 } }, "Members"), memberError && /* @__PURE__ */ import_react5.default.createElement(import_Alert2.default, { severity: "error", sx: { mb: 1 }, onClose: () => setMemberError(null) }, memberError), members.length === 0 ? /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "body2", color: "text.secondary" }, "No members yet.") : /* @__PURE__ */ import_react5.default.createElement(import_List.default, { dense: true, disablePadding: true }, members.map((m) => /* @__PURE__ */ import_react5.default.createElement(
2208
- import_ListItem.default,
2256
+ ), showMembers && /* @__PURE__ */ import_react5.default.createElement(import_Box5.default, null, /* @__PURE__ */ import_react5.default.createElement(import_Divider2.default, { sx: { my: 1 } }), /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "subtitle2", sx: { mb: 1 } }, "Members"), memberError && /* @__PURE__ */ import_react5.default.createElement(import_Alert2.default, { severity: "error", sx: { mb: 1 }, onClose: () => setMemberError(null) }, memberError), members.length === 0 ? /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "body2", color: "text.secondary", sx: { mb: 1 } }, "No members yet.") : /* @__PURE__ */ import_react5.default.createElement(import_TableContainer2.default, { component: import_Paper3.default, variant: "outlined", sx: { borderRadius: 1.5, mb: 1.5 } }, /* @__PURE__ */ import_react5.default.createElement(import_Table2.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react5.default.createElement(import_TableHead2.default, null, /* @__PURE__ */ import_react5.default.createElement(import_TableRow2.default, null, /* @__PURE__ */ import_react5.default.createElement(import_TableCell2.default, null, "User"), /* @__PURE__ */ import_react5.default.createElement(import_TableCell2.default, { align: "right" }, "Role"), /* @__PURE__ */ import_react5.default.createElement(import_TableCell2.default, { align: "right", sx: { width: 40 } }))), /* @__PURE__ */ import_react5.default.createElement(import_TableBody2.default, null, members.map((m) => /* @__PURE__ */ import_react5.default.createElement(import_TableRow2.default, { key: m.user_id }, /* @__PURE__ */ import_react5.default.createElement(import_TableCell2.default, null, m.user_email ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "body2" }, m.user_email), /* @__PURE__ */ import_react5.default.createElement(
2257
+ import_Typography5.default,
2209
2258
  {
2210
- key: m.user_id,
2211
- disableGutters: true,
2212
- secondaryAction: /* @__PURE__ */ import_react5.default.createElement(
2213
- import_IconButton3.default,
2214
- {
2215
- edge: "end",
2216
- size: "small",
2217
- "aria-label": `remove ${m.user_id}`,
2218
- disabled: memberBusy,
2219
- onClick: () => handleRemoveMember(m.user_id)
2220
- },
2221
- /* @__PURE__ */ import_react5.default.createElement(import_icons_material4.Delete, { fontSize: "small" })
2222
- )
2259
+ variant: "caption",
2260
+ color: "text.secondary",
2261
+ sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 }
2223
2262
  },
2224
- /* @__PURE__ */ import_react5.default.createElement(import_ListItemText.default, { primary: m.user_id, secondary: m.role })
2225
- ))), /* @__PURE__ */ import_react5.default.createElement(import_Box5.default, { sx: { display: "flex", gap: 1, alignItems: "flex-start", mt: 1 } }, /* @__PURE__ */ import_react5.default.createElement(
2226
- import_TextField3.default,
2263
+ m.user_id
2264
+ )) : /* @__PURE__ */ import_react5.default.createElement(
2265
+ import_Typography5.default,
2227
2266
  {
2228
- label: "Backstage user ref",
2229
- placeholder: "user:default/alice",
2230
- value: memberRef,
2231
- onChange: (e) => setMemberRef(e.target.value),
2232
- disabled: memberBusy,
2267
+ variant: "body2",
2268
+ sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" }
2269
+ },
2270
+ m.user_id
2271
+ )), /* @__PURE__ */ import_react5.default.createElement(import_TableCell2.default, { align: "right" }, /* @__PURE__ */ import_react5.default.createElement(StatusPill, { label: m.role, tone: m.role === "admin" ? "accent" : "neutral", dot: false })), /* @__PURE__ */ import_react5.default.createElement(import_TableCell2.default, { align: "right" }, /* @__PURE__ */ import_react5.default.createElement(
2272
+ import_IconButton3.default,
2273
+ {
2274
+ edge: "end",
2233
2275
  size: "small",
2234
- sx: { flex: 1 }
2276
+ "aria-label": `remove ${m.user_id}`,
2277
+ disabled: memberBusy,
2278
+ onClick: () => handleRemoveMember(m.user_id)
2279
+ },
2280
+ /* @__PURE__ */ import_react5.default.createElement(import_icons_material4.Delete, { fontSize: "small" })
2281
+ ))))))), /* @__PURE__ */ import_react5.default.createElement(import_Box5.default, { sx: { display: "flex", gap: 1, alignItems: "flex-start", flexWrap: "wrap" } }, /* @__PURE__ */ import_react5.default.createElement(
2282
+ import_Autocomplete3.default,
2283
+ {
2284
+ freeSolo: true,
2285
+ autoHighlight: true,
2286
+ options: userOptions,
2287
+ loading: usersLoading,
2288
+ inputValue: memberQuery,
2289
+ onInputChange: (_, newInputValue, reason) => {
2290
+ setMemberQuery(newInputValue);
2291
+ if (reason === "input" || reason === "clear") {
2292
+ setMemberRef(newInputValue);
2293
+ }
2294
+ },
2295
+ onChange: (_, newValue) => {
2296
+ if (newValue && typeof newValue !== "string") {
2297
+ setMemberQuery(newValue.label);
2298
+ setMemberRef(newValue.ref);
2299
+ }
2300
+ },
2301
+ getOptionLabel: (o) => typeof o === "string" ? o : o.label,
2302
+ isOptionEqualToValue: (o, v) => o.ref === (typeof v === "string" ? v : v.ref),
2303
+ disabled: memberBusy,
2304
+ sx: { flex: 1, minWidth: 260 },
2305
+ renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(
2306
+ import_TextField3.default,
2307
+ {
2308
+ ...params,
2309
+ label: "Add member",
2310
+ placeholder: "Search by name or email\u2026",
2311
+ size: "small",
2312
+ helperText: "Pick a catalog user, or paste a user entity ref",
2313
+ InputProps: {
2314
+ ...params.InputProps,
2315
+ endAdornment: /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, usersLoading ? /* @__PURE__ */ import_react5.default.createElement(import_CircularProgress3.default, { color: "inherit", size: 14 }) : null, params.InputProps.endAdornment)
2316
+ }
2317
+ }
2318
+ )
2235
2319
  }
2236
2320
  ), /* @__PURE__ */ import_react5.default.createElement(
2237
2321
  import_TextField3.default,
@@ -2302,23 +2386,23 @@ function rateTone(rate) {
2302
2386
  if (rate >= 0.9) return "warning";
2303
2387
  return "danger";
2304
2388
  }
2305
- var import_react6, import_Paper3, import_Box6, import_Typography6, import_TextField4, import_MenuItem3, import_Grid, import_Table2, import_TableBody2, import_TableCell2, import_TableContainer2, import_TableHead2, import_TableRow2, import_Skeleton3, import_recharts, TOP_N_MODELS, PERIOD_LS_KEY, PRESET_LABELS, fmtPct, ChartSkeleton, ChartOrFallback, SuccessRateCell, UsageStats;
2389
+ var import_react6, import_Paper4, import_Box6, import_Typography6, import_TextField4, import_MenuItem3, import_Grid, import_Table3, import_TableBody3, import_TableCell3, import_TableContainer3, import_TableHead3, import_TableRow3, import_Skeleton3, import_recharts, TOP_N_MODELS, PERIOD_LS_KEY, PRESET_LABELS, fmtPct, ChartSkeleton, ChartOrFallback, SuccessRateCell, UsageStats;
2306
2390
  var init_UsageStats = __esm({
2307
2391
  "src/components/UsageStats.tsx"() {
2308
2392
  "use strict";
2309
2393
  import_react6 = __toESM(require("react"));
2310
- import_Paper3 = __toESM(require("@mui/material/Paper"));
2394
+ import_Paper4 = __toESM(require("@mui/material/Paper"));
2311
2395
  import_Box6 = __toESM(require("@mui/material/Box"));
2312
2396
  import_Typography6 = __toESM(require("@mui/material/Typography"));
2313
2397
  import_TextField4 = __toESM(require("@mui/material/TextField"));
2314
2398
  import_MenuItem3 = __toESM(require("@mui/material/MenuItem"));
2315
2399
  import_Grid = __toESM(require("@mui/material/Grid"));
2316
- import_Table2 = __toESM(require("@mui/material/Table"));
2317
- import_TableBody2 = __toESM(require("@mui/material/TableBody"));
2318
- import_TableCell2 = __toESM(require("@mui/material/TableCell"));
2319
- import_TableContainer2 = __toESM(require("@mui/material/TableContainer"));
2320
- import_TableHead2 = __toESM(require("@mui/material/TableHead"));
2321
- import_TableRow2 = __toESM(require("@mui/material/TableRow"));
2400
+ import_Table3 = __toESM(require("@mui/material/Table"));
2401
+ import_TableBody3 = __toESM(require("@mui/material/TableBody"));
2402
+ import_TableCell3 = __toESM(require("@mui/material/TableCell"));
2403
+ import_TableContainer3 = __toESM(require("@mui/material/TableContainer"));
2404
+ import_TableHead3 = __toESM(require("@mui/material/TableHead"));
2405
+ import_TableRow3 = __toESM(require("@mui/material/TableRow"));
2322
2406
  import_Skeleton3 = __toESM(require("@mui/material/Skeleton"));
2323
2407
  import_recharts = require("recharts");
2324
2408
  init_format();
@@ -2490,21 +2574,21 @@ var init_UsageStats = __esm({
2490
2574
  ];
2491
2575
  const renderKeyRows = () => {
2492
2576
  if (loading) {
2493
- return /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { colSpan: 7, sx: { py: 3 } }, /* @__PURE__ */ import_react6.default.createElement(import_Skeleton3.default, { variant: "rounded", height: 80 })));
2577
+ return /* @__PURE__ */ import_react6.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { colSpan: 7, sx: { py: 3 } }, /* @__PURE__ */ import_react6.default.createElement(import_Skeleton3.default, { variant: "rounded", height: 80 })));
2494
2578
  }
2495
2579
  if (keyRows.length === 0) {
2496
- return /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { colSpan: 7 }, /* @__PURE__ */ import_react6.default.createElement(EmptyState, { message: "No key activity in this period" })));
2580
+ return /* @__PURE__ */ import_react6.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { colSpan: 7 }, /* @__PURE__ */ import_react6.default.createElement(EmptyState, { message: "No key activity in this period" })));
2497
2581
  }
2498
- return [...keyRows].sort((a, b) => b.spend - a.spend || b.apiRequests - a.apiRequests).map((r) => /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, { key: r.keyHash }, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Typography6.default, { variant: "body2", sx: { fontWeight: 600 } }, r.keyAlias), r.teamId ? /* @__PURE__ */ import_react6.default.createElement(import_Typography6.default, { variant: "caption", color: "text.secondary" }, "team: ", r.teamId) : null), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Box6.default, { display: "flex", gap: 0.5, flexWrap: "wrap" }, r.models.slice(0, 3).map((m) => /* @__PURE__ */ import_react6.default.createElement(TagChip, { key: m, label: m, title: m })), r.models.length > 3 && /* @__PURE__ */ import_react6.default.createElement(TagChip, { label: `+${r.models.length - 3}`, mono: false }))), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtUsd(r.spend)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtInt(r.apiRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtCompact(r.totalTokens)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtInt(r.failedRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, /* @__PURE__ */ import_react6.default.createElement(SuccessRateCell, { rate: r.successRate, requests: r.apiRequests }))));
2582
+ return [...keyRows].sort((a, b) => b.spend - a.spend || b.apiRequests - a.apiRequests).map((r) => /* @__PURE__ */ import_react6.default.createElement(import_TableRow3.default, { key: r.keyHash }, /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Typography6.default, { variant: "body2", sx: { fontWeight: 600 } }, r.keyAlias), r.teamId ? /* @__PURE__ */ import_react6.default.createElement(import_Typography6.default, { variant: "caption", color: "text.secondary" }, "team: ", r.teamId) : null), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Box6.default, { display: "flex", gap: 0.5, flexWrap: "wrap" }, r.models.slice(0, 3).map((m) => /* @__PURE__ */ import_react6.default.createElement(TagChip, { key: m, label: m, title: m })), r.models.length > 3 && /* @__PURE__ */ import_react6.default.createElement(TagChip, { label: `+${r.models.length - 3}`, mono: false }))), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtUsd(r.spend)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.apiRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtCompact(r.totalTokens)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.failedRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react6.default.createElement(SuccessRateCell, { rate: r.successRate, requests: r.apiRequests }))));
2499
2583
  };
2500
2584
  const renderModelRows = () => {
2501
2585
  if (loading) {
2502
- return /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { colSpan: 8, sx: { py: 3 } }, /* @__PURE__ */ import_react6.default.createElement(import_Skeleton3.default, { variant: "rounded", height: 80 })));
2586
+ return /* @__PURE__ */ import_react6.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { colSpan: 8, sx: { py: 3 } }, /* @__PURE__ */ import_react6.default.createElement(import_Skeleton3.default, { variant: "rounded", height: 80 })));
2503
2587
  }
2504
2588
  if (modelRows.length === 0) {
2505
- return /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { colSpan: 8 }, /* @__PURE__ */ import_react6.default.createElement(EmptyState, { message: "No model activity in this period" })));
2589
+ return /* @__PURE__ */ import_react6.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { colSpan: 8 }, /* @__PURE__ */ import_react6.default.createElement(EmptyState, { message: "No model activity in this period" })));
2506
2590
  }
2507
- return [...modelRows].sort((a, b) => b.spend - a.spend || b.totalTokens - a.totalTokens).map((r) => /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, { key: r.model }, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Box6.default, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ import_react6.default.createElement(import_Box6.default, { sx: { width: 8, height: 8, borderRadius: "50%", bgcolor: chartColor(r.model), flexShrink: 0 } }), /* @__PURE__ */ import_react6.default.createElement(import_Typography6.default, { variant: "body2", sx: { fontWeight: 600 } }, r.model))), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtUsd(r.spend)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtInt(r.apiRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtInt(r.successfulRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtInt(r.failedRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtCompact(r.promptTokens)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, fmtCompact(r.completionTokens)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, /* @__PURE__ */ import_react6.default.createElement(SuccessRateCell, { rate: r.successRate, requests: r.apiRequests }))));
2591
+ return [...modelRows].sort((a, b) => b.spend - a.spend || b.totalTokens - a.totalTokens).map((r) => /* @__PURE__ */ import_react6.default.createElement(import_TableRow3.default, { key: r.model }, /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Box6.default, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ import_react6.default.createElement(import_Box6.default, { sx: { width: 8, height: 8, borderRadius: "50%", bgcolor: chartColor(r.model), flexShrink: 0 } }), /* @__PURE__ */ import_react6.default.createElement(import_Typography6.default, { variant: "body2", sx: { fontWeight: 600 } }, r.model))), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtUsd(r.spend)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.apiRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.successfulRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.failedRequests)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtCompact(r.promptTokens)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, fmtCompact(r.completionTokens)), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react6.default.createElement(SuccessRateCell, { rate: r.successRate, requests: r.apiRequests }))));
2508
2592
  };
2509
2593
  const periodSelect = /* @__PURE__ */ import_react6.default.createElement(
2510
2594
  import_TextField4.default,
@@ -2657,7 +2741,7 @@ var init_UsageStats = __esm({
2657
2741
  height: Math.max(200, topModelSpendBars.length * 34)
2658
2742
  },
2659
2743
  /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.BarChart, { data: topModelSpendBars, layout: "vertical", margin: { top: 0, right: 12, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { ...chart.grid, vertical: true, horizontal: false }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { type: "number", tickFormatter: fmtCompact, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { type: "category", dataKey: "model", width: 170, ...chart.axis, tick: { fontSize: 10.5, fill: chart.axis.tick.fill } }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react6.default.createElement(ChartTooltip, { valueFormatter: fmtInt, labelFormatter: (l) => l }) }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Legend, { ...chart.legend }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Bar, { dataKey: "promptTokens", name: "Input", fill: SERIES.input, stackId: "t", barSize: 14 }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Bar, { dataKey: "completionTokens", name: "Output", fill: SERIES.output, stackId: "t", barSize: 14, radius: [0, 3, 3, 0] })))
2660
- ))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react6.default.createElement(import_TableContainer2.default, { component: import_Paper3.default, variant: "outlined", sx: { borderRadius: 2 } }, /* @__PURE__ */ import_react6.default.createElement(import_Table2.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react6.default.createElement(import_TableHead2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, "Model"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Spend"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Requests"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Success"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Failed"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Input"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Output"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { sx: { width: 160 } }, "Success rate"))), /* @__PURE__ */ import_react6.default.createElement(import_TableBody2.default, null, renderModelRows()))))),
2744
+ ))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react6.default.createElement(import_TableContainer3.default, { component: import_Paper4.default, variant: "outlined", sx: { borderRadius: 2 } }, /* @__PURE__ */ import_react6.default.createElement(import_Table3.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react6.default.createElement(import_TableHead3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, null, "Model"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Spend"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Requests"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Success"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Failed"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Input"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Output"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { sx: { width: 160 } }, "Success rate"))), /* @__PURE__ */ import_react6.default.createElement(import_TableBody3.default, null, renderModelRows()))))),
2661
2745
  tab === "keys" && /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { container: true, spacing: 2 }, (loading || topKeySpendBars.length > 0) && /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react6.default.createElement(ChartCard, { title: "Spend by key", height: Math.max(160, topKeySpendBars.length * 32) }, /* @__PURE__ */ import_react6.default.createElement(
2662
2746
  ChartOrFallback,
2663
2747
  {
@@ -2666,7 +2750,7 @@ var init_UsageStats = __esm({
2666
2750
  height: Math.max(160, topKeySpendBars.length * 32)
2667
2751
  },
2668
2752
  /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.BarChart, { data: topKeySpendBars, layout: "vertical", margin: { top: 0, right: 12, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { ...chart.grid, vertical: true, horizontal: false }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { type: "number", tickFormatter: fmtUsdCompact, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { type: "category", dataKey: "keyAlias", width: 160, ...chart.axis, tick: { fontSize: 10.5, fill: chart.axis.tick.fill } }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react6.default.createElement(ChartTooltip, { valueFormatter: fmtUsd, labelFormatter: (l) => l }) }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Bar, { dataKey: "spend", name: "Spend", fill: SERIES.input, radius: [0, 3, 3, 0], barSize: 14 })))
2669
- ))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react6.default.createElement(import_TableContainer2.default, { component: import_Paper3.default, variant: "outlined", sx: { borderRadius: 2 } }, /* @__PURE__ */ import_react6.default.createElement(import_Table2.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react6.default.createElement(import_TableHead2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, "Key"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, "Models"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Spend"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Requests"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Tokens"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Failed"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { sx: { width: 160 } }, "Success rate"))), /* @__PURE__ */ import_react6.default.createElement(import_TableBody2.default, null, renderKeyRows())))))
2753
+ ))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react6.default.createElement(import_TableContainer3.default, { component: import_Paper4.default, variant: "outlined", sx: { borderRadius: 2 } }, /* @__PURE__ */ import_react6.default.createElement(import_Table3.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react6.default.createElement(import_TableHead3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, null, "Key"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, null, "Models"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Spend"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Requests"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Tokens"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { align: "right" }, "Failed"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell3.default, { sx: { width: 160 } }, "Success rate"))), /* @__PURE__ */ import_react6.default.createElement(import_TableBody3.default, null, renderKeyRows())))))
2670
2754
  );
2671
2755
  };
2672
2756
  }
@@ -2678,26 +2762,26 @@ function budgetTone2(isOver, isNear) {
2678
2762
  if (isNear) return "warning";
2679
2763
  return "accent";
2680
2764
  }
2681
- var import_react7, import_Paper4, import_Box7, import_Typography7, import_Skeleton4, import_Divider3, import_Table3, import_TableBody3, import_TableCell3, import_TableHead3, import_TableRow3, import_TableContainer3, import_Collapse, import_IconButton4, import_Button5, import_CircularProgress3, import_styles4, import_icons_material5, import_recharts2, fmtUsd2, TeamCard, TeamUsage;
2765
+ var import_react7, import_Paper5, import_Box7, import_Typography7, import_Skeleton4, import_Divider3, import_Table4, import_TableBody4, import_TableCell4, import_TableHead4, import_TableRow4, import_TableContainer4, import_Collapse, import_IconButton4, import_Button5, import_CircularProgress4, import_styles4, import_icons_material5, import_recharts2, fmtUsd2, TeamCard, TeamUsage;
2682
2766
  var init_TeamUsage = __esm({
2683
2767
  "src/components/TeamUsage.tsx"() {
2684
2768
  "use strict";
2685
2769
  import_react7 = __toESM(require("react"));
2686
- import_Paper4 = __toESM(require("@mui/material/Paper"));
2770
+ import_Paper5 = __toESM(require("@mui/material/Paper"));
2687
2771
  import_Box7 = __toESM(require("@mui/material/Box"));
2688
2772
  import_Typography7 = __toESM(require("@mui/material/Typography"));
2689
2773
  import_Skeleton4 = __toESM(require("@mui/material/Skeleton"));
2690
2774
  import_Divider3 = __toESM(require("@mui/material/Divider"));
2691
- import_Table3 = __toESM(require("@mui/material/Table"));
2692
- import_TableBody3 = __toESM(require("@mui/material/TableBody"));
2693
- import_TableCell3 = __toESM(require("@mui/material/TableCell"));
2694
- import_TableHead3 = __toESM(require("@mui/material/TableHead"));
2695
- import_TableRow3 = __toESM(require("@mui/material/TableRow"));
2696
- import_TableContainer3 = __toESM(require("@mui/material/TableContainer"));
2775
+ import_Table4 = __toESM(require("@mui/material/Table"));
2776
+ import_TableBody4 = __toESM(require("@mui/material/TableBody"));
2777
+ import_TableCell4 = __toESM(require("@mui/material/TableCell"));
2778
+ import_TableHead4 = __toESM(require("@mui/material/TableHead"));
2779
+ import_TableRow4 = __toESM(require("@mui/material/TableRow"));
2780
+ import_TableContainer4 = __toESM(require("@mui/material/TableContainer"));
2697
2781
  import_Collapse = __toESM(require("@mui/material/Collapse"));
2698
2782
  import_IconButton4 = __toESM(require("@mui/material/IconButton"));
2699
2783
  import_Button5 = __toESM(require("@mui/material/Button"));
2700
- import_CircularProgress3 = __toESM(require("@mui/material/CircularProgress"));
2784
+ import_CircularProgress4 = __toESM(require("@mui/material/CircularProgress"));
2701
2785
  import_styles4 = require("@mui/material/styles");
2702
2786
  import_icons_material5 = require("@mui/icons-material");
2703
2787
  import_recharts2 = require("recharts");
@@ -2714,7 +2798,7 @@ var init_TeamUsage = __esm({
2714
2798
  const dailyData = usage?.daily_usage?.map((d) => ({ date: d.date, spend: d.spend })) ?? [];
2715
2799
  const renderDailySpendSection = () => {
2716
2800
  if (usageLoading) {
2717
- return /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { display: "flex", justifyContent: "center", py: 3 }, /* @__PURE__ */ import_react7.default.createElement(import_CircularProgress3.default, { size: 22 }));
2801
+ return /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { display: "flex", justifyContent: "center", py: 3 }, /* @__PURE__ */ import_react7.default.createElement(import_CircularProgress4.default, { size: 22 }));
2718
2802
  }
2719
2803
  if (dailyData.length === 0) return null;
2720
2804
  return /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { mb: 2.5 }, /* @__PURE__ */ import_react7.default.createElement(
@@ -2753,7 +2837,7 @@ var init_TeamUsage = __esm({
2753
2837
  },
2754
2838
  label
2755
2839
  );
2756
- return /* @__PURE__ */ import_react7.default.createElement(import_Paper4.default, { variant: "outlined", sx: { borderRadius: 2, p: 2.5 } }, /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { display: "flex", alignItems: "center", gap: 1.5 }, /* @__PURE__ */ import_react7.default.createElement(
2840
+ return /* @__PURE__ */ import_react7.default.createElement(import_Paper5.default, { variant: "outlined", sx: { borderRadius: 2, p: 2.5 } }, /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { display: "flex", alignItems: "center", gap: 1.5 }, /* @__PURE__ */ import_react7.default.createElement(
2757
2841
  import_Box7.default,
2758
2842
  {
2759
2843
  sx: (theme) => ({
@@ -2818,13 +2902,13 @@ var init_TeamUsage = __esm({
2818
2902
  /* @__PURE__ */ import_react7.default.createElement(Stat, { label: "TPM", value: team.tpm_limit && team.tpm_limit > 0 ? team.tpm_limit.toLocaleString() : "\u2014" }),
2819
2903
  /* @__PURE__ */ import_react7.default.createElement(Stat, { label: "RPM", value: team.rpm_limit && team.rpm_limit > 0 ? team.rpm_limit.toLocaleString() : "\u2014" })
2820
2904
  ), budget > 0 && /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { mt: 2, maxWidth: 640 }, /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { display: "flex", justifyContent: "space-between", alignItems: "baseline", mb: 0.75 }, /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, fmtUsd2(spend), " of ", fmtUsd2(budget)), /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, budgetPct.toFixed(0), "%")), /* @__PURE__ */ import_react7.default.createElement(Meter, { value: budgetPct, tone: budgetTone2(isOver, isNear), height: 5 })), /* @__PURE__ */ import_react7.default.createElement(import_Collapse.default, { in: expanded, unmountOnExit: true }, /* @__PURE__ */ import_react7.default.createElement(import_Divider3.default, { sx: { my: 2.5 } }), /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { mb: 2.5 }, sectionLabel("Models"), team.models?.length ? /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { display: "flex", gap: 0.5, flexWrap: "wrap" }, team.models.map((m) => /* @__PURE__ */ import_react7.default.createElement(TagChip, { key: m, label: m, title: m }))) : /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "body2", color: "text.secondary" }, "All models allowed")), renderDailySpendSection(), /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, null, sectionLabel("Members"), team.members_with_roles?.length ? /* @__PURE__ */ import_react7.default.createElement(
2821
- import_TableContainer3.default,
2905
+ import_TableContainer4.default,
2822
2906
  {
2823
- component: import_Paper4.default,
2907
+ component: import_Paper5.default,
2824
2908
  variant: "outlined",
2825
2909
  sx: { borderRadius: 1.5 }
2826
2910
  },
2827
- /* @__PURE__ */ import_react7.default.createElement(import_Table3.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react7.default.createElement(import_TableHead3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, null, "User"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Role"))), /* @__PURE__ */ import_react7.default.createElement(import_TableBody3.default, null, team.members_with_roles.map((m) => /* @__PURE__ */ import_react7.default.createElement(import_TableRow3.default, { key: m.user_id }, /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, null, m.user_email ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "body2" }, m.user_email), /* @__PURE__ */ import_react7.default.createElement(
2911
+ /* @__PURE__ */ import_react7.default.createElement(import_Table4.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react7.default.createElement(import_TableHead4.default, null, /* @__PURE__ */ import_react7.default.createElement(import_TableRow4.default, null, /* @__PURE__ */ import_react7.default.createElement(import_TableCell4.default, null, "User"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell4.default, { align: "right" }, "Role"))), /* @__PURE__ */ import_react7.default.createElement(import_TableBody4.default, null, team.members_with_roles.map((m) => /* @__PURE__ */ import_react7.default.createElement(import_TableRow4.default, { key: m.user_id }, /* @__PURE__ */ import_react7.default.createElement(import_TableCell4.default, null, m.user_email ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "body2" }, m.user_email), /* @__PURE__ */ import_react7.default.createElement(
2828
2912
  import_Typography7.default,
2829
2913
  {
2830
2914
  variant: "caption",
@@ -2839,7 +2923,7 @@ var init_TeamUsage = __esm({
2839
2923
  sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" }
2840
2924
  },
2841
2925
  m.user_id
2842
- )), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, /* @__PURE__ */ import_react7.default.createElement(
2926
+ )), /* @__PURE__ */ import_react7.default.createElement(import_TableCell4.default, { align: "right" }, /* @__PURE__ */ import_react7.default.createElement(
2843
2927
  StatusPill,
2844
2928
  {
2845
2929
  label: m.role,
@@ -2855,13 +2939,26 @@ var init_TeamUsage = __esm({
2855
2939
  getTeamUsage,
2856
2940
  getTeamUsageLoading,
2857
2941
  canManage,
2858
- onEditTeam
2942
+ onEditTeam,
2943
+ canCreate,
2944
+ onCreateTeam
2859
2945
  }) => {
2946
+ const createAction = canCreate && onCreateTeam ? /* @__PURE__ */ import_react7.default.createElement(
2947
+ import_Button5.default,
2948
+ {
2949
+ variant: "contained",
2950
+ color: "primary",
2951
+ disableElevation: true,
2952
+ startIcon: /* @__PURE__ */ import_react7.default.createElement(import_icons_material5.Add, null),
2953
+ onClick: onCreateTeam
2954
+ },
2955
+ "Create Team"
2956
+ ) : void 0;
2860
2957
  if (loading) {
2861
- return /* @__PURE__ */ import_react7.default.createElement(SectionCard, { title: "Teams" }, /* @__PURE__ */ import_react7.default.createElement(import_Skeleton4.default, { variant: "rounded", height: 120, sx: { mb: 2 } }), /* @__PURE__ */ import_react7.default.createElement(import_Skeleton4.default, { variant: "rounded", height: 120 }));
2958
+ return /* @__PURE__ */ import_react7.default.createElement(SectionCard, { title: "Teams", actions: createAction }, /* @__PURE__ */ import_react7.default.createElement(import_Skeleton4.default, { variant: "rounded", height: 120, sx: { mb: 2 } }), /* @__PURE__ */ import_react7.default.createElement(import_Skeleton4.default, { variant: "rounded", height: 120 }));
2862
2959
  }
2863
2960
  if (!teams.length) {
2864
- return /* @__PURE__ */ import_react7.default.createElement(SectionCard, { title: "Teams" }, /* @__PURE__ */ import_react7.default.createElement(
2961
+ return /* @__PURE__ */ import_react7.default.createElement(SectionCard, { title: "Teams", actions: createAction }, /* @__PURE__ */ import_react7.default.createElement(
2865
2962
  EmptyState,
2866
2963
  {
2867
2964
  message: "You're not a member of any LiteLLM team yet.",
@@ -2869,17 +2966,25 @@ var init_TeamUsage = __esm({
2869
2966
  }
2870
2967
  ));
2871
2968
  }
2872
- return /* @__PURE__ */ import_react7.default.createElement(SectionCard, { title: "Teams", subtitle: `${teams.length} team${teams.length === 1 ? "" : "s"}` }, /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, teams.map((team) => /* @__PURE__ */ import_react7.default.createElement(
2873
- TeamCard,
2969
+ return /* @__PURE__ */ import_react7.default.createElement(
2970
+ SectionCard,
2874
2971
  {
2875
- key: team.team_id,
2876
- team,
2877
- usage: getTeamUsage(team.team_id),
2878
- usageLoading: getTeamUsageLoading(team.team_id),
2879
- canManage,
2880
- onEditTeam
2881
- }
2882
- ))));
2972
+ title: "Teams",
2973
+ subtitle: `${teams.length} team${teams.length === 1 ? "" : "s"}`,
2974
+ actions: createAction
2975
+ },
2976
+ /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, teams.map((team) => /* @__PURE__ */ import_react7.default.createElement(
2977
+ TeamCard,
2978
+ {
2979
+ key: team.team_id,
2980
+ team,
2981
+ usage: getTeamUsage(team.team_id),
2982
+ usageLoading: getTeamUsageLoading(team.team_id),
2983
+ canManage,
2984
+ onEditTeam
2985
+ }
2986
+ )))
2987
+ );
2883
2988
  };
2884
2989
  }
2885
2990
  });
@@ -2902,18 +3007,18 @@ function fmtTokens(n) {
2902
3007
  if (n >= 1e3) return `${(n / 1e3).toFixed(0)}K`;
2903
3008
  return String(n);
2904
3009
  }
2905
- var import_react8, import_Box8, import_Table4, import_TableBody4, import_TableCell4, import_TableContainer4, import_TableHead4, import_TableRow4, import_Typography8, import_MenuItem4, import_Select, import_FormControl, import_InputLabel, import_ContentCopy, import_Tooltip, import_Snackbar, import_Alert3, import_styles5, ALL_PROXY_MODELS2, ModelsTable;
3010
+ var import_react8, import_Box8, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_Typography8, import_MenuItem4, import_Select, import_FormControl, import_InputLabel, import_ContentCopy, import_Tooltip, import_Snackbar, import_Alert3, import_styles5, ALL_PROXY_MODELS2, ModelsTable;
2906
3011
  var init_ModelsTable = __esm({
2907
3012
  "src/components/ModelsTable.tsx"() {
2908
3013
  "use strict";
2909
3014
  import_react8 = __toESM(require("react"));
2910
3015
  import_Box8 = __toESM(require("@mui/material/Box"));
2911
- import_Table4 = __toESM(require("@mui/material/Table"));
2912
- import_TableBody4 = __toESM(require("@mui/material/TableBody"));
2913
- import_TableCell4 = __toESM(require("@mui/material/TableCell"));
2914
- import_TableContainer4 = __toESM(require("@mui/material/TableContainer"));
2915
- import_TableHead4 = __toESM(require("@mui/material/TableHead"));
2916
- import_TableRow4 = __toESM(require("@mui/material/TableRow"));
3016
+ import_Table5 = __toESM(require("@mui/material/Table"));
3017
+ import_TableBody5 = __toESM(require("@mui/material/TableBody"));
3018
+ import_TableCell5 = __toESM(require("@mui/material/TableCell"));
3019
+ import_TableContainer5 = __toESM(require("@mui/material/TableContainer"));
3020
+ import_TableHead5 = __toESM(require("@mui/material/TableHead"));
3021
+ import_TableRow5 = __toESM(require("@mui/material/TableRow"));
2917
3022
  import_Typography8 = __toESM(require("@mui/material/Typography"));
2918
3023
  import_MenuItem4 = __toESM(require("@mui/material/MenuItem"));
2919
3024
  import_Select = __toESM(require("@mui/material/Select"));
@@ -2986,7 +3091,7 @@ var init_ModelsTable = __esm({
2986
3091
  hint: allModels.length === 0 ? "No models are configured in the system" : "None of the team's assigned models were found in the catalog"
2987
3092
  }
2988
3093
  ),
2989
- !loading && filteredModels.length > 0 && /* @__PURE__ */ import_react8.default.createElement(import_TableContainer4.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Table4.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react8.default.createElement(import_TableHead4.default, null, /* @__PURE__ */ import_react8.default.createElement(import_TableRow4.default, null, /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, null, "Model ID"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, null, "Mode"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, { align: "right" }, "Input Cost"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, { align: "right" }, "Output Cost"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, { align: "right" }, "Max Input"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, { align: "right" }, "Max Output"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, null, "Capabilities"))), /* @__PURE__ */ import_react8.default.createElement(import_TableBody4.default, null, filteredModels.map((m) => /* @__PURE__ */ import_react8.default.createElement(import_TableRow4.default, { key: m.model_name, hover: true }, /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ import_react8.default.createElement(TagChip, { label: m.model_name, title: m.model_name }), /* @__PURE__ */ import_react8.default.createElement(import_Tooltip.default, { title: "Copy model ID" }, /* @__PURE__ */ import_react8.default.createElement(
3094
+ !loading && filteredModels.length > 0 && /* @__PURE__ */ import_react8.default.createElement(import_TableContainer5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Table5.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react8.default.createElement(import_TableHead5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Model ID"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Mode"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Input Cost"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Output Cost"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Max Input"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Max Output"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Capabilities"))), /* @__PURE__ */ import_react8.default.createElement(import_TableBody5.default, null, filteredModels.map((m) => /* @__PURE__ */ import_react8.default.createElement(import_TableRow5.default, { key: m.model_name, hover: true }, /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ import_react8.default.createElement(TagChip, { label: m.model_name, title: m.model_name }), /* @__PURE__ */ import_react8.default.createElement(import_Tooltip.default, { title: "Copy model ID" }, /* @__PURE__ */ import_react8.default.createElement(
2990
3095
  import_Box8.default,
2991
3096
  {
2992
3097
  component: "span",
@@ -2998,7 +3103,7 @@ var init_ModelsTable = __esm({
2998
3103
  style: { cursor: "pointer", display: "inline-flex" }
2999
3104
  },
3000
3105
  /* @__PURE__ */ import_react8.default.createElement(import_ContentCopy.default, { sx: { fontSize: 14 } })
3001
- )))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, null, /* @__PURE__ */ import_react8.default.createElement(
3106
+ )))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react8.default.createElement(
3002
3107
  import_Box8.default,
3003
3108
  {
3004
3109
  component: "span",
@@ -3015,7 +3120,7 @@ var init_ModelsTable = __esm({
3015
3120
  }
3016
3121
  },
3017
3122
  m.mode
3018
- )), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, { align: "right" }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtCostPerToken(m.input_cost_per_token))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, { align: "right" }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtCostPerToken(m.output_cost_per_token))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, { align: "right" }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtTokens(m.max_input_tokens))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, { align: "right" }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtTokens(m.max_output_tokens))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell4.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap" } }, m.supports_function_calling && /* @__PURE__ */ import_react8.default.createElement(TagChip, { label: "Fn", title: "Function calling" }), m.supports_vision && /* @__PURE__ */ import_react8.default.createElement(TagChip, { label: "\u{1F441}", title: "Vision" })))))))),
3123
+ )), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtCostPerToken(m.input_cost_per_token))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtCostPerToken(m.output_cost_per_token))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtTokens(m.max_input_tokens))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtTokens(m.max_output_tokens))), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap" } }, m.supports_function_calling && /* @__PURE__ */ import_react8.default.createElement(TagChip, { label: "Fn", title: "Function calling" }), m.supports_vision && /* @__PURE__ */ import_react8.default.createElement(TagChip, { label: "\u{1F441}", title: "Vision" })))))))),
3019
3124
  /* @__PURE__ */ import_react8.default.createElement(
3020
3125
  import_Snackbar.default,
3021
3126
  {
@@ -3052,10 +3157,10 @@ function formatDateTime(iso) {
3052
3157
  }
3053
3158
  function renderAuditLogBody(loading, entries) {
3054
3159
  if (loading) {
3055
- return /* @__PURE__ */ import_react9.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, { colSpan: 6, sx: { py: 2 } }, /* @__PURE__ */ import_react9.default.createElement(import_Skeleton5.default, { variant: "rounded", height: 160 })));
3160
+ return /* @__PURE__ */ import_react9.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, { colSpan: 6, sx: { py: 2 } }, /* @__PURE__ */ import_react9.default.createElement(import_Skeleton5.default, { variant: "rounded", height: 160 })));
3056
3161
  }
3057
3162
  if (entries.length === 0) {
3058
- return /* @__PURE__ */ import_react9.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, { colSpan: 6 }, /* @__PURE__ */ import_react9.default.createElement(
3163
+ return /* @__PURE__ */ import_react9.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, { colSpan: 6 }, /* @__PURE__ */ import_react9.default.createElement(
3059
3164
  EmptyState,
3060
3165
  {
3061
3166
  message: "No audit events found",
@@ -3065,19 +3170,19 @@ function renderAuditLogBody(loading, entries) {
3065
3170
  }
3066
3171
  return entries.map((entry) => /* @__PURE__ */ import_react9.default.createElement(DetailRow, { key: entry.id, entry }));
3067
3172
  }
3068
- var import_react9, import_Box9, import_Typography9, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_TablePagination, import_TextField5, import_MenuItem5, import_Skeleton5, import_Collapse2, import_IconButton5, import_Alert4, import_styles6, import_icons_material6, import_react_use, ACTION_TONES, TABLE_LABELS, DetailRow, AuditLog;
3173
+ var import_react9, import_Box9, import_Typography9, import_Table6, import_TableBody6, import_TableCell6, import_TableContainer6, import_TableHead6, import_TableRow6, import_TablePagination, import_TextField5, import_MenuItem5, import_Skeleton5, import_Collapse2, import_IconButton5, import_Alert4, import_styles6, import_icons_material6, import_react_use2, ACTION_TONES, TABLE_LABELS, DetailRow, AuditLog;
3069
3174
  var init_AuditLog = __esm({
3070
3175
  "src/components/AuditLog.tsx"() {
3071
3176
  "use strict";
3072
3177
  import_react9 = __toESM(require("react"));
3073
3178
  import_Box9 = __toESM(require("@mui/material/Box"));
3074
3179
  import_Typography9 = __toESM(require("@mui/material/Typography"));
3075
- import_Table5 = __toESM(require("@mui/material/Table"));
3076
- import_TableBody5 = __toESM(require("@mui/material/TableBody"));
3077
- import_TableCell5 = __toESM(require("@mui/material/TableCell"));
3078
- import_TableContainer5 = __toESM(require("@mui/material/TableContainer"));
3079
- import_TableHead5 = __toESM(require("@mui/material/TableHead"));
3080
- import_TableRow5 = __toESM(require("@mui/material/TableRow"));
3180
+ import_Table6 = __toESM(require("@mui/material/Table"));
3181
+ import_TableBody6 = __toESM(require("@mui/material/TableBody"));
3182
+ import_TableCell6 = __toESM(require("@mui/material/TableCell"));
3183
+ import_TableContainer6 = __toESM(require("@mui/material/TableContainer"));
3184
+ import_TableHead6 = __toESM(require("@mui/material/TableHead"));
3185
+ import_TableRow6 = __toESM(require("@mui/material/TableRow"));
3081
3186
  import_TablePagination = __toESM(require("@mui/material/TablePagination"));
3082
3187
  import_TextField5 = __toESM(require("@mui/material/TextField"));
3083
3188
  import_MenuItem5 = __toESM(require("@mui/material/MenuItem"));
@@ -3087,7 +3192,7 @@ var init_AuditLog = __esm({
3087
3192
  import_Alert4 = __toESM(require("@mui/material/Alert"));
3088
3193
  import_styles6 = require("@mui/material/styles");
3089
3194
  import_icons_material6 = require("@mui/icons-material");
3090
- import_react_use = require("react-use");
3195
+ import_react_use2 = require("react-use");
3091
3196
  init_ui();
3092
3197
  ACTION_TONES = {
3093
3198
  created: "success",
@@ -3106,7 +3211,7 @@ var init_AuditLog = __esm({
3106
3211
  DetailRow = ({ entry }) => {
3107
3212
  const [open, setOpen] = (0, import_react9.useState)(false);
3108
3213
  const hasDetail = entry.before_value || entry.updated_values;
3109
- return /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, { sx: { width: 40, pr: 0 } }, hasDetail && /* @__PURE__ */ import_react9.default.createElement(
3214
+ return /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, { sx: { width: 40, pr: 0 } }, hasDetail && /* @__PURE__ */ import_react9.default.createElement(
3110
3215
  import_IconButton5.default,
3111
3216
  {
3112
3217
  size: "small",
@@ -3120,7 +3225,7 @@ var init_AuditLog = __esm({
3120
3225
  })
3121
3226
  },
3122
3227
  /* @__PURE__ */ import_react9.default.createElement(import_icons_material6.KeyboardArrowDown, { fontSize: "small" })
3123
- )), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, { sx: { whiteSpace: "nowrap" } }, /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "body2", color: "text.secondary" }, formatDateTime(entry.updated_at))), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, entry.action && /* @__PURE__ */ import_react9.default.createElement(StatusPill, { label: entry.action, tone: actionTone(entry.action) })), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "body2" }, prettyTableName(entry.table_name))), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react9.default.createElement(
3228
+ )), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, { sx: { whiteSpace: "nowrap" } }, /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "body2", color: "text.secondary" }, formatDateTime(entry.updated_at))), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, entry.action && /* @__PURE__ */ import_react9.default.createElement(StatusPill, { label: entry.action, tone: actionTone(entry.action) })), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "body2" }, prettyTableName(entry.table_name))), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, /* @__PURE__ */ import_react9.default.createElement(
3124
3229
  import_Typography9.default,
3125
3230
  {
3126
3231
  variant: "body2",
@@ -3130,7 +3235,7 @@ var init_AuditLog = __esm({
3130
3235
  sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 12 }
3131
3236
  },
3132
3237
  entry.object_id ? entry.object_id.slice(0, 20) + (entry.object_id.length > 20 ? "\u2026" : "") : "\u2014"
3133
- )), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, entry.changed_by ?? "\u2014")), hasDetail && /* @__PURE__ */ import_react9.default.createElement(import_TableRow5.default, { sx: { "&&:hover": { bgcolor: "transparent" } } }, /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, { colSpan: 6, sx: { "&&": { py: 0, border: 0 } } }, /* @__PURE__ */ import_react9.default.createElement(import_Collapse2.default, { in: open, unmountOnExit: true }, /* @__PURE__ */ import_react9.default.createElement(
3238
+ )), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, entry.changed_by ?? "\u2014")), hasDetail && /* @__PURE__ */ import_react9.default.createElement(import_TableRow6.default, { sx: { "&&:hover": { bgcolor: "transparent" } } }, /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, { colSpan: 6, sx: { "&&": { py: 0, border: 0 } } }, /* @__PURE__ */ import_react9.default.createElement(import_Collapse2.default, { in: open, unmountOnExit: true }, /* @__PURE__ */ import_react9.default.createElement(
3134
3239
  import_Box9.default,
3135
3240
  {
3136
3241
  display: "flex",
@@ -3175,7 +3280,7 @@ var init_AuditLog = __esm({
3175
3280
  () => ({ page: page + 1, page_size: pageSize, ...filters }),
3176
3281
  [page, pageSize, filters]
3177
3282
  )();
3178
- const { value, loading, error } = (0, import_react_use.useAsync)(
3283
+ const { value, loading, error } = (0, import_react_use2.useAsync)(
3179
3284
  () => api.getAuditLogs(fetchParams),
3180
3285
  [api, fetchParams]
3181
3286
  );
@@ -3239,7 +3344,7 @@ var init_AuditLog = __esm({
3239
3344
  ))
3240
3345
  },
3241
3346
  error && /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { px: 2.5, pb: 2 }, /* @__PURE__ */ import_react9.default.createElement(import_Alert4.default, { severity: "error" }, error.message)),
3242
- /* @__PURE__ */ import_react9.default.createElement(import_TableContainer5.default, null, /* @__PURE__ */ import_react9.default.createElement(import_Table5.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react9.default.createElement(import_TableHead5.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, { sx: { width: 40 } }), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, "Time"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, "Action"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, "Table"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, "Object ID"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell5.default, null, "Changed By"))), /* @__PURE__ */ import_react9.default.createElement(import_TableBody5.default, null, renderAuditLogBody(loading, entries)))),
3347
+ /* @__PURE__ */ import_react9.default.createElement(import_TableContainer6.default, null, /* @__PURE__ */ import_react9.default.createElement(import_Table6.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react9.default.createElement(import_TableHead6.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, { sx: { width: 40 } }), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, "Time"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, "Action"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, "Table"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, "Object ID"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell6.default, null, "Changed By"))), /* @__PURE__ */ import_react9.default.createElement(import_TableBody6.default, null, renderAuditLogBody(loading, entries)))),
3243
3348
  /* @__PURE__ */ import_react9.default.createElement(
3244
3349
  import_TablePagination.default,
3245
3350
  {
@@ -3309,7 +3414,7 @@ function initDateRange() {
3309
3414
  else start.setDate(start.getDate() - 7);
3310
3415
  return { start, end };
3311
3416
  }
3312
- var import_react10, import_Box10, import_Snackbar2, import_Alert5, import_CircularProgress4, import_Typography10, import_Paper5, import_Tabs2, import_Tab2, import_Button6, import_react_use2, import_core_plugin_api2, import_plugin_permission_react, PERIOD_LS_KEY2, LiteLLMPage;
3417
+ var import_react10, import_Box10, import_Snackbar2, import_Alert5, import_CircularProgress5, import_Typography10, import_Paper6, import_Tabs2, import_Tab2, import_react_use3, import_core_plugin_api3, import_plugin_permission_react, PERIOD_LS_KEY2, LiteLLMPage;
3313
3418
  var init_LiteLLMPage = __esm({
3314
3419
  "src/components/LiteLLMPage.tsx"() {
3315
3420
  "use strict";
@@ -3317,14 +3422,13 @@ var init_LiteLLMPage = __esm({
3317
3422
  import_Box10 = __toESM(require("@mui/material/Box"));
3318
3423
  import_Snackbar2 = __toESM(require("@mui/material/Snackbar"));
3319
3424
  import_Alert5 = __toESM(require("@mui/material/Alert"));
3320
- import_CircularProgress4 = __toESM(require("@mui/material/CircularProgress"));
3425
+ import_CircularProgress5 = __toESM(require("@mui/material/CircularProgress"));
3321
3426
  import_Typography10 = __toESM(require("@mui/material/Typography"));
3322
- import_Paper5 = __toESM(require("@mui/material/Paper"));
3427
+ import_Paper6 = __toESM(require("@mui/material/Paper"));
3323
3428
  import_Tabs2 = __toESM(require("@mui/material/Tabs"));
3324
3429
  import_Tab2 = __toESM(require("@mui/material/Tab"));
3325
- import_Button6 = __toESM(require("@mui/material/Button"));
3326
- import_react_use2 = require("react-use");
3327
- import_core_plugin_api2 = require("@backstage/core-plugin-api");
3430
+ import_react_use3 = require("react-use");
3431
+ import_core_plugin_api3 = require("@backstage/core-plugin-api");
3328
3432
  import_plugin_permission_react = require("@backstage/plugin-permission-react");
3329
3433
  init_DashboardHeader();
3330
3434
  init_KeysTable();
@@ -3338,7 +3442,7 @@ var init_LiteLLMPage = __esm({
3338
3442
  init_permissions();
3339
3443
  PERIOD_LS_KEY2 = "litellm_usage_period";
3340
3444
  LiteLLMPage = () => {
3341
- const api = (0, import_core_plugin_api2.useApi)(liteLlmApiRef);
3445
+ const api = (0, import_core_plugin_api3.useApi)(liteLlmApiRef);
3342
3446
  const [dateRange, setDateRange] = (0, import_react10.useState)(initDateRange);
3343
3447
  const [currentPreset, setCurrentPreset] = (0, import_react10.useState)(() => {
3344
3448
  try {
@@ -3353,11 +3457,11 @@ var init_LiteLLMPage = __esm({
3353
3457
  const [manageTeam, setManageTeam] = (0, import_react10.useState)(null);
3354
3458
  const [teamUsageCache, setTeamUsageCache] = (0, import_react10.useState)({});
3355
3459
  const [teamUsageLoading, setTeamUsageLoading] = (0, import_react10.useState)({});
3356
- const { value: userInfo, loading: userLoading, error: userError } = (0, import_react_use2.useAsync)(
3460
+ const { value: userInfo, loading: userLoading, error: userError } = (0, import_react_use3.useAsync)(
3357
3461
  () => api.getUserInfo(),
3358
3462
  [api]
3359
3463
  );
3360
- const { value: keys, loading: keysLoading, retry: refreshKeys } = (0, import_react_use2.useAsyncRetry)(
3464
+ const { value: keys, loading: keysLoading, retry: refreshKeys } = (0, import_react_use3.useAsyncRetry)(
3361
3465
  async () => {
3362
3466
  try {
3363
3467
  return await api.listKeys();
@@ -3368,16 +3472,16 @@ var init_LiteLLMPage = __esm({
3368
3472
  },
3369
3473
  [api]
3370
3474
  );
3371
- const { value: allModels, loading: modelsLoading } = (0, import_react_use2.useAsync)(
3475
+ const { value: allModels, loading: modelsLoading } = (0, import_react_use3.useAsync)(
3372
3476
  () => api.listModels().catch(() => []),
3373
3477
  [api]
3374
3478
  );
3375
- const { value: allTeams, loading: teamsLoading, retry: refreshTeams } = (0, import_react_use2.useAsyncRetry)(
3479
+ const { value: allTeams, loading: teamsLoading, retry: refreshTeams } = (0, import_react_use3.useAsyncRetry)(
3376
3480
  () => api.getTeams().catch(() => []),
3377
3481
  [api]
3378
3482
  );
3379
- const { value: liteLlmConfig } = (0, import_react_use2.useAsync)(() => api.getConfig(), [api]);
3380
- const { value: managedTeams } = (0, import_react_use2.useAsync)(
3483
+ const { value: liteLlmConfig } = (0, import_react_use3.useAsync)(() => api.getConfig(), [api]);
3484
+ const { value: managedTeams } = (0, import_react_use3.useAsync)(
3381
3485
  async () => liteLlmConfig?.teamManagement?.enabled ? api.getManagedTeams().catch(() => []) : [],
3382
3486
  [api, liteLlmConfig]
3383
3487
  );
@@ -3388,11 +3492,11 @@ var init_LiteLLMPage = __esm({
3388
3492
  const { allowed: canManageMcpServers } = (0, import_plugin_permission_react.usePermission)({ permission: litellmTeamMcpManagePermission });
3389
3493
  const teamMgmtEnabled = liteLlmConfig?.teamManagement?.enabled ?? false;
3390
3494
  const objectPermsEnabled = liteLlmConfig?.teamManagement?.objectPermissionsEnabled ?? false;
3391
- const { value: vectorStores } = (0, import_react_use2.useAsync)(
3495
+ const { value: vectorStores } = (0, import_react_use3.useAsync)(
3392
3496
  async () => objectPermsEnabled ? api.getVectorStores().catch(() => []) : [],
3393
3497
  [api, objectPermsEnabled]
3394
3498
  );
3395
- const { value: mcpServers } = (0, import_react_use2.useAsync)(
3499
+ const { value: mcpServers } = (0, import_react_use3.useAsync)(
3396
3500
  async () => objectPermsEnabled ? api.getMcpServers().catch(() => []) : [],
3397
3501
  [api, objectPermsEnabled]
3398
3502
  );
@@ -3408,7 +3512,7 @@ var init_LiteLLMPage = __esm({
3408
3512
  );
3409
3513
  return byMembership.length > 0 ? byMembership : allTeams;
3410
3514
  }, [allTeams, userInfo]);
3411
- const { value: usage, loading: usageLoading } = (0, import_react_use2.useAsync)(async () => {
3515
+ const { value: usage, loading: usageLoading } = (0, import_react_use3.useAsync)(async () => {
3412
3516
  const startDate = dateRange.start.toISOString().split("T")[0];
3413
3517
  const endDate = dateRange.end.toISOString().split("T")[0];
3414
3518
  return api.getUsage(startDate, endDate);
@@ -3543,12 +3647,12 @@ var init_LiteLLMPage = __esm({
3543
3647
  );
3544
3648
  const isInitialLoading = userLoading && !userInfo;
3545
3649
  if (isInitialLoading) {
3546
- return /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "50vh" }, /* @__PURE__ */ import_react10.default.createElement(import_CircularProgress4.default, null));
3650
+ return /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "50vh" }, /* @__PURE__ */ import_react10.default.createElement(import_CircularProgress5.default, null));
3547
3651
  }
3548
3652
  if (userError || !userInfo) {
3549
3653
  const isProvisioningEnabled = userError?.body?.provisioning === true;
3550
3654
  const hint = userError?.body?.hint;
3551
- return /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { p: 3 }, /* @__PURE__ */ import_react10.default.createElement(import_Paper5.default, { sx: { p: 3 } }, /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "h6", gutterBottom: true }, "Account not provisioned"), /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { color: "text.secondary", paragraph: true }, "Your Backstage account is not linked to a LiteLLM user."), hint ? /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "body2", color: "text.secondary" }, hint) : /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "body2", color: "text.secondary" }, isProvisioningEnabled ? "Auto-provisioning is enabled but failed. Check the backend logs." : "Set litellm.provisioning.enabled: true in app-config.yaml to enable auto-provisioning, or ask your administrator to create the account manually.")));
3655
+ return /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { p: 3 }, /* @__PURE__ */ import_react10.default.createElement(import_Paper6.default, { sx: { p: 3 } }, /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "h6", gutterBottom: true }, "Account not provisioned"), /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { color: "text.secondary", paragraph: true }, "Your Backstage account is not linked to a LiteLLM user."), hint ? /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "body2", color: "text.secondary" }, hint) : /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "body2", color: "text.secondary" }, isProvisioningEnabled ? "Auto-provisioning is enabled but failed. Check the backend logs." : "Set litellm.provisioning.enabled: true in app-config.yaml to enable auto-provisioning, or ask your administrator to create the account manually.")));
3552
3656
  }
3553
3657
  const pageTabs = /* @__PURE__ */ import_react10.default.createElement(
3554
3658
  import_Tabs2.default,
@@ -3609,14 +3713,7 @@ var init_LiteLLMPage = __esm({
3609
3713
  for (const t of managedTeams ?? []) teamsById.set(t.team_id, t);
3610
3714
  for (const t of teams ?? []) teamsById.set(t.team_id, t);
3611
3715
  const visibleTeams = Array.from(teamsById.values());
3612
- return /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, teamMgmtEnabled && canCreateTeam && /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { sx: { display: "flex", justifyContent: "flex-end" } }, /* @__PURE__ */ import_react10.default.createElement(
3613
- import_Button6.default,
3614
- {
3615
- variant: "contained",
3616
- onClick: () => setManageTeam({ mode: "create" })
3617
- },
3618
- "Create Team"
3619
- )), /* @__PURE__ */ import_react10.default.createElement(
3716
+ return /* @__PURE__ */ import_react10.default.createElement(
3620
3717
  TeamUsage,
3621
3718
  {
3622
3719
  teams: visibleTeams,
@@ -3627,9 +3724,11 @@ var init_LiteLLMPage = __esm({
3627
3724
  },
3628
3725
  getTeamUsageLoading: (teamId) => teamUsageLoading[teamId] ?? false,
3629
3726
  canManage: teamMgmtEnabled && canManageTeam,
3630
- onEditTeam: (t) => setManageTeam({ mode: "edit", team: t })
3727
+ onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
3728
+ canCreate: teamMgmtEnabled && canCreateTeam,
3729
+ onCreateTeam: () => setManageTeam({ mode: "create" })
3631
3730
  }
3632
- ));
3731
+ );
3633
3732
  })(), activeTab === "models" && /* @__PURE__ */ import_react10.default.createElement(
3634
3733
  ModelsTable,
3635
3734
  {
@@ -3785,17 +3884,17 @@ init_TeamUsage();
3785
3884
 
3786
3885
  // src/components/LiteLLMHomeWidget.tsx
3787
3886
  var import_react12 = __toESM(require("react"));
3788
- var import_Paper6 = __toESM(require("@mui/material/Paper"));
3887
+ var import_Paper7 = __toESM(require("@mui/material/Paper"));
3789
3888
  var import_Box11 = __toESM(require("@mui/material/Box"));
3790
3889
  var import_Typography11 = __toESM(require("@mui/material/Typography"));
3791
3890
  var import_FormControl2 = __toESM(require("@mui/material/FormControl"));
3792
3891
  var import_Select2 = __toESM(require("@mui/material/Select"));
3793
3892
  var import_MenuItem6 = __toESM(require("@mui/material/MenuItem"));
3794
3893
  var import_Grid2 = __toESM(require("@mui/material/Grid"));
3795
- var import_CircularProgress5 = __toESM(require("@mui/material/CircularProgress"));
3894
+ var import_CircularProgress6 = __toESM(require("@mui/material/CircularProgress"));
3796
3895
  var import_Alert6 = __toESM(require("@mui/material/Alert"));
3797
3896
  var import_recharts3 = require("recharts");
3798
- var import_core_plugin_api3 = require("@backstage/core-plugin-api");
3897
+ var import_core_plugin_api4 = require("@backstage/core-plugin-api");
3799
3898
  init_api();
3800
3899
  init_format();
3801
3900
  function presetToDateRange(preset) {
@@ -3815,7 +3914,7 @@ var LiteLLMHomeWidget = ({
3815
3914
  defaultPeriod = "7d",
3816
3915
  title = "LiteLLM Usage"
3817
3916
  }) => {
3818
- const api = (0, import_core_plugin_api3.useApi)(liteLlmApiRef);
3917
+ const api = (0, import_core_plugin_api4.useApi)(liteLlmApiRef);
3819
3918
  const [period, setPeriod] = (0, import_react12.useState)(defaultPeriod);
3820
3919
  const [loading, setLoading] = (0, import_react12.useState)(true);
3821
3920
  const [usageError, setUsageError] = (0, import_react12.useState)(null);
@@ -3859,7 +3958,7 @@ var LiteLLMHomeWidget = ({
3859
3958
  spend: d.spend
3860
3959
  }));
3861
3960
  const hasSparkline = dailyData.length > 0;
3862
- return /* @__PURE__ */ import_react12.default.createElement(import_Paper6.default, { sx: { p: 2 } }, /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1.5 }, /* @__PURE__ */ import_react12.default.createElement(import_Typography11.default, { variant: "h6" }, title), /* @__PURE__ */ import_react12.default.createElement(import_FormControl2.default, { size: "small", sx: { minWidth: 90 } }, /* @__PURE__ */ import_react12.default.createElement(
3961
+ return /* @__PURE__ */ import_react12.default.createElement(import_Paper7.default, { sx: { p: 2 } }, /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1.5 }, /* @__PURE__ */ import_react12.default.createElement(import_Typography11.default, { variant: "h6" }, title), /* @__PURE__ */ import_react12.default.createElement(import_FormControl2.default, { size: "small", sx: { minWidth: 90 } }, /* @__PURE__ */ import_react12.default.createElement(
3863
3962
  import_Select2.default,
3864
3963
  {
3865
3964
  value: period,
@@ -3869,7 +3968,7 @@ var LiteLLMHomeWidget = ({
3869
3968
  /* @__PURE__ */ import_react12.default.createElement(import_MenuItem6.default, { value: "today" }, "Today"),
3870
3969
  /* @__PURE__ */ import_react12.default.createElement(import_MenuItem6.default, { value: "7d" }, "7d"),
3871
3970
  /* @__PURE__ */ import_react12.default.createElement(import_MenuItem6.default, { value: "30d" }, "30d")
3872
- ))), loading && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 120 }, /* @__PURE__ */ import_react12.default.createElement(import_CircularProgress5.default, { size: 32 })), !loading && totalFailure && /* @__PURE__ */ import_react12.default.createElement(import_Alert6.default, { severity: "error", sx: { mt: 1 } }, usageError ?? "Failed to load usage data"), !loading && !totalFailure && /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, partialFailure && /* @__PURE__ */ import_react12.default.createElement(import_Alert6.default, { severity: "warning", sx: { mt: 1, mb: 1 } }, usageError ? `Usage data unavailable (${usageError}).` : "", keysError ? ` Key list unavailable (${keysError}).` : "", " Showing what loaded."), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { container: true, spacing: 2, sx: { mb: hasSparkline ? 1.5 : 0 } }, /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "USD Spent", value: fmtUsd(usage?.total_spend ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Tokens In", value: fmtInt(usage?.prompt_tokens ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Tokens Out", value: fmtInt(usage?.completion_tokens ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Keys", value: fmtInt(keys.length) }))), hasSparkline && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { height: 120 }, /* @__PURE__ */ import_react12.default.createElement(import_recharts3.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react12.default.createElement(import_recharts3.AreaChart, { data: dailyData, margin: { top: 4, right: 0, bottom: 0, left: 0 } }, /* @__PURE__ */ import_react12.default.createElement(
3971
+ ))), loading && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 120 }, /* @__PURE__ */ import_react12.default.createElement(import_CircularProgress6.default, { size: 32 })), !loading && totalFailure && /* @__PURE__ */ import_react12.default.createElement(import_Alert6.default, { severity: "error", sx: { mt: 1 } }, usageError ?? "Failed to load usage data"), !loading && !totalFailure && /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, partialFailure && /* @__PURE__ */ import_react12.default.createElement(import_Alert6.default, { severity: "warning", sx: { mt: 1, mb: 1 } }, usageError ? `Usage data unavailable (${usageError}).` : "", keysError ? ` Key list unavailable (${keysError}).` : "", " Showing what loaded."), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { container: true, spacing: 2, sx: { mb: hasSparkline ? 1.5 : 0 } }, /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "USD Spent", value: fmtUsd(usage?.total_spend ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Tokens In", value: fmtInt(usage?.prompt_tokens ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Tokens Out", value: fmtInt(usage?.completion_tokens ?? 0) })), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react12.default.createElement(Kpi, { label: "Keys", value: fmtInt(keys.length) }))), hasSparkline && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { height: 120 }, /* @__PURE__ */ import_react12.default.createElement(import_recharts3.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react12.default.createElement(import_recharts3.AreaChart, { data: dailyData, margin: { top: 4, right: 0, bottom: 0, left: 0 } }, /* @__PURE__ */ import_react12.default.createElement(
3873
3972
  import_recharts3.Area,
3874
3973
  {
3875
3974
  type: "monotone",