@acarmisc/backstage-plugin-litellm 0.26.0 → 0.27.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
@@ -858,6 +858,66 @@ var init_ui = __esm({
858
858
  }
859
859
  });
860
860
 
861
+ // src/components/GenerateKeyButton.tsx
862
+ var import_react2, import_Button, import_icons_material, import_core_components, GenerateKeyButton;
863
+ var init_GenerateKeyButton = __esm({
864
+ "src/components/GenerateKeyButton.tsx"() {
865
+ "use strict";
866
+ import_react2 = __toESM(require("react"));
867
+ import_Button = __toESM(require("@mui/material/Button"));
868
+ import_icons_material = require("@mui/icons-material");
869
+ import_core_components = require("@backstage/core-components");
870
+ GenerateKeyButton = ({
871
+ to,
872
+ onClick,
873
+ label = "Generate New Key",
874
+ size
875
+ }) => {
876
+ if (onClick) {
877
+ return /* @__PURE__ */ import_react2.default.createElement(
878
+ import_Button.default,
879
+ {
880
+ variant: "contained",
881
+ color: "primary",
882
+ disableElevation: true,
883
+ size,
884
+ startIcon: /* @__PURE__ */ import_react2.default.createElement(import_icons_material.Add, null),
885
+ onClick
886
+ },
887
+ label
888
+ );
889
+ }
890
+ if (to) {
891
+ return /* @__PURE__ */ import_react2.default.createElement(
892
+ import_Button.default,
893
+ {
894
+ variant: "contained",
895
+ color: "primary",
896
+ disableElevation: true,
897
+ size,
898
+ startIcon: /* @__PURE__ */ import_react2.default.createElement(import_icons_material.Add, null),
899
+ component: import_core_components.Link,
900
+ to
901
+ },
902
+ label
903
+ );
904
+ }
905
+ return /* @__PURE__ */ import_react2.default.createElement(
906
+ import_Button.default,
907
+ {
908
+ variant: "contained",
909
+ color: "primary",
910
+ disableElevation: true,
911
+ size,
912
+ startIcon: /* @__PURE__ */ import_react2.default.createElement(import_icons_material.Add, null),
913
+ disabled: true
914
+ },
915
+ label
916
+ );
917
+ };
918
+ }
919
+ });
920
+
861
921
  // src/components/DashboardHeader.tsx
862
922
  function initials(name) {
863
923
  const local = name.split("@")[0] ?? name;
@@ -865,24 +925,23 @@ function initials(name) {
865
925
  if (parts.length >= 2) return (parts[0][0] + parts[1][0]).toUpperCase();
866
926
  return local.slice(0, 2).toUpperCase();
867
927
  }
868
- var import_react2, import_Box2, import_Typography2, import_Skeleton, import_Paper2, import_Button, import_Divider, import_styles2, import_icons_material, CountStat, DashboardHeader;
928
+ var import_react3, import_Box2, import_Typography2, import_Skeleton, import_Paper2, import_Divider, import_styles2, CountStat, DashboardHeader;
869
929
  var init_DashboardHeader = __esm({
870
930
  "src/components/DashboardHeader.tsx"() {
871
931
  "use strict";
872
- import_react2 = __toESM(require("react"));
932
+ import_react3 = __toESM(require("react"));
873
933
  import_Box2 = __toESM(require("@mui/material/Box"));
874
934
  import_Typography2 = __toESM(require("@mui/material/Typography"));
875
935
  import_Skeleton = __toESM(require("@mui/material/Skeleton"));
876
936
  import_Paper2 = __toESM(require("@mui/material/Paper"));
877
- import_Button = __toESM(require("@mui/material/Button"));
878
937
  import_Divider = __toESM(require("@mui/material/Divider"));
879
938
  import_styles2 = require("@mui/material/styles");
880
- import_icons_material = require("@mui/icons-material");
881
939
  init_api();
882
940
  init_ui();
941
+ init_GenerateKeyButton();
883
942
  CountStat = ({ value, label, tone }) => {
884
943
  const active = value > 0;
885
- return /* @__PURE__ */ import_react2.default.createElement(import_Box2.default, { sx: { display: "flex", alignItems: "center", gap: 1 } }, /* @__PURE__ */ import_react2.default.createElement(
944
+ return /* @__PURE__ */ import_react3.default.createElement(import_Box2.default, { sx: { display: "flex", alignItems: "center", gap: 1 } }, /* @__PURE__ */ import_react3.default.createElement(
886
945
  import_Box2.default,
887
946
  {
888
947
  sx: (theme) => ({
@@ -893,14 +952,14 @@ var init_DashboardHeader = __esm({
893
952
  bgcolor: active ? tone === "danger" && theme.palette.error.main || tone === "warning" && theme.palette.warning.main || theme.palette.primary.main : (0, import_styles2.alpha)(theme.palette.text.primary, 0.25)
894
953
  })
895
954
  }
896
- ), /* @__PURE__ */ import_react2.default.createElement(
955
+ ), /* @__PURE__ */ import_react3.default.createElement(
897
956
  import_Typography2.default,
898
957
  {
899
958
  component: "span",
900
959
  sx: { fontSize: 15, fontWeight: 700, lineHeight: 1, fontVariantNumeric: "tabular-nums" }
901
960
  },
902
961
  value
903
- ), /* @__PURE__ */ import_react2.default.createElement(
962
+ ), /* @__PURE__ */ import_react3.default.createElement(
904
963
  import_Typography2.default,
905
964
  {
906
965
  component: "span",
@@ -918,13 +977,13 @@ var init_DashboardHeader = __esm({
918
977
  onGenerateKeyClick,
919
978
  tabs
920
979
  }) => {
921
- const counts = (0, import_react2.useMemo)(() => {
980
+ const counts = (0, import_react3.useMemo)(() => {
922
981
  const expired = keys.filter((k) => expiryStatus(k.expires_at) === "expired").length;
923
982
  const expiringSoon = keys.filter((k) => expiryStatus(k.expires_at) === "soon").length;
924
983
  return { total: keys.length, expired, expiringSoon };
925
984
  }, [keys]);
926
985
  const displayName = userInfo.user_email ?? userInfo.email ?? userInfo.user_id;
927
- return /* @__PURE__ */ import_react2.default.createElement(import_Paper2.default, { sx: { borderRadius: 2, overflow: "hidden" } }, /* @__PURE__ */ import_react2.default.createElement(
986
+ return /* @__PURE__ */ import_react3.default.createElement(import_Paper2.default, { sx: { borderRadius: 2, overflow: "hidden" } }, /* @__PURE__ */ import_react3.default.createElement(
928
987
  import_Box2.default,
929
988
  {
930
989
  sx: {
@@ -937,7 +996,7 @@ var init_DashboardHeader = __esm({
937
996
  pb: 2
938
997
  }
939
998
  },
940
- /* @__PURE__ */ import_react2.default.createElement(
999
+ /* @__PURE__ */ import_react3.default.createElement(
941
1000
  import_Box2.default,
942
1001
  {
943
1002
  sx: (theme) => ({
@@ -957,7 +1016,7 @@ var init_DashboardHeader = __esm({
957
1016
  },
958
1017
  initials(displayName)
959
1018
  ),
960
- /* @__PURE__ */ import_react2.default.createElement(import_Box2.default, { sx: { flexGrow: 1, minWidth: 220 } }, /* @__PURE__ */ import_react2.default.createElement(import_Typography2.default, { variant: "h6", sx: { lineHeight: 1.25, wordBreak: "break-word" } }, displayName), /* @__PURE__ */ import_react2.default.createElement(
1019
+ /* @__PURE__ */ import_react3.default.createElement(import_Box2.default, { sx: { flexGrow: 1, minWidth: 220 } }, /* @__PURE__ */ import_react3.default.createElement(import_Typography2.default, { variant: "h6", sx: { lineHeight: 1.25, wordBreak: "break-word" } }, displayName), /* @__PURE__ */ import_react3.default.createElement(
961
1020
  import_Typography2.default,
962
1021
  {
963
1022
  variant: "caption",
@@ -965,7 +1024,7 @@ var init_DashboardHeader = __esm({
965
1024
  sx: { display: "block", fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" }
966
1025
  },
967
1026
  userInfo.user_id
968
- ), /* @__PURE__ */ import_react2.default.createElement(import_Box2.default, { sx: { display: "flex", gap: 0.75, flexWrap: "wrap", mt: 1, minHeight: 20 } }, loading ? /* @__PURE__ */ import_react2.default.createElement(import_Skeleton.default, { variant: "rounded", width: 140, height: 20 }) : teams.map((team) => /* @__PURE__ */ import_react2.default.createElement(
1027
+ ), /* @__PURE__ */ import_react3.default.createElement(import_Box2.default, { sx: { display: "flex", gap: 0.75, flexWrap: "wrap", mt: 1, minHeight: 20 } }, loading ? /* @__PURE__ */ import_react3.default.createElement(import_Skeleton.default, { variant: "rounded", width: 140, height: 20 }) : teams.map((team) => /* @__PURE__ */ import_react3.default.createElement(
969
1028
  TagChip,
970
1029
  {
971
1030
  key: team.team_id,
@@ -973,18 +1032,8 @@ var init_DashboardHeader = __esm({
973
1032
  title: team.team_id
974
1033
  }
975
1034
  )))),
976
- /* @__PURE__ */ import_react2.default.createElement(
977
- import_Button.default,
978
- {
979
- variant: "contained",
980
- color: "primary",
981
- disableElevation: true,
982
- startIcon: /* @__PURE__ */ import_react2.default.createElement(import_icons_material.Add, null),
983
- onClick: onGenerateKeyClick
984
- },
985
- "Generate New Key"
986
- )
987
- ), /* @__PURE__ */ import_react2.default.createElement(import_Divider.default, null), /* @__PURE__ */ import_react2.default.createElement(
1035
+ /* @__PURE__ */ import_react3.default.createElement(GenerateKeyButton, { onClick: onGenerateKeyClick })
1036
+ ), /* @__PURE__ */ import_react3.default.createElement(import_Divider.default, null), /* @__PURE__ */ import_react3.default.createElement(
988
1037
  import_Box2.default,
989
1038
  {
990
1039
  sx: {
@@ -996,12 +1045,12 @@ var init_DashboardHeader = __esm({
996
1045
  py: 1.5
997
1046
  }
998
1047
  },
999
- /* @__PURE__ */ import_react2.default.createElement(CountStat, { value: counts.total, label: "keys", tone: "accent" }),
1000
- /* @__PURE__ */ import_react2.default.createElement(import_Divider.default, { orientation: "vertical", flexItem: true, sx: { my: 0.25 } }),
1001
- /* @__PURE__ */ import_react2.default.createElement(CountStat, { value: counts.expired, label: "expired", tone: "danger" }),
1002
- /* @__PURE__ */ import_react2.default.createElement(import_Divider.default, { orientation: "vertical", flexItem: true, sx: { my: 0.25 } }),
1003
- /* @__PURE__ */ import_react2.default.createElement(CountStat, { value: counts.expiringSoon, label: "expiring soon", tone: "warning" })
1004
- ), tabs && /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement(import_Divider.default, null), /* @__PURE__ */ import_react2.default.createElement(import_Box2.default, { sx: { px: 1 } }, tabs)));
1048
+ /* @__PURE__ */ import_react3.default.createElement(CountStat, { value: counts.total, label: "keys", tone: "accent" }),
1049
+ /* @__PURE__ */ import_react3.default.createElement(import_Divider.default, { orientation: "vertical", flexItem: true, sx: { my: 0.25 } }),
1050
+ /* @__PURE__ */ import_react3.default.createElement(CountStat, { value: counts.expired, label: "expired", tone: "danger" }),
1051
+ /* @__PURE__ */ import_react3.default.createElement(import_Divider.default, { orientation: "vertical", flexItem: true, sx: { my: 0.25 } }),
1052
+ /* @__PURE__ */ import_react3.default.createElement(CountStat, { value: counts.expiringSoon, label: "expiring soon", tone: "warning" })
1053
+ ), tabs && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement(import_Divider.default, null), /* @__PURE__ */ import_react3.default.createElement(import_Box2.default, { sx: { px: 1 } }, tabs)));
1005
1054
  };
1006
1055
  }
1007
1056
  });
@@ -1020,12 +1069,12 @@ function expiryTone(status) {
1020
1069
  function ExpiryCell({ expiresAt }) {
1021
1070
  const status = expiryStatus(expiresAt);
1022
1071
  if (!status) {
1023
- return /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary" }, "Never");
1072
+ return /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary" }, "Never");
1024
1073
  }
1025
1074
  if (status === "ok") {
1026
- return /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary" }, formatDate(expiresAt));
1075
+ return /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary" }, formatDate(expiresAt));
1027
1076
  }
1028
- return /* @__PURE__ */ import_react3.default.createElement(
1077
+ return /* @__PURE__ */ import_react4.default.createElement(
1029
1078
  StatusPill,
1030
1079
  {
1031
1080
  label: expiryChipLabel(status, expiresAt),
@@ -1040,16 +1089,16 @@ function budgetTone(pct) {
1040
1089
  return "accent";
1041
1090
  }
1042
1091
  function keyBlockIcon(isBlocking, blocked) {
1043
- if (isBlocking) return /* @__PURE__ */ import_react3.default.createElement(import_CircularProgress.default, { size: 18 });
1044
- if (blocked) return /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.LockOpen, { fontSize: "small" });
1045
- return /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Lock, { fontSize: "small" });
1092
+ if (isBlocking) return /* @__PURE__ */ import_react4.default.createElement(import_CircularProgress.default, { size: 18 });
1093
+ if (blocked) return /* @__PURE__ */ import_react4.default.createElement(import_icons_material2.LockOpen, { fontSize: "small" });
1094
+ return /* @__PURE__ */ import_react4.default.createElement(import_icons_material2.Lock, { fontSize: "small" });
1046
1095
  }
1047
1096
  function BudgetCell({ spend, maxBudget }) {
1048
1097
  if (!maxBudget) {
1049
- return /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, "$", spend.toFixed(2), /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { component: "span", variant: "caption", sx: { ml: 0.5, opacity: 0.7 } }, "/ \u221E"));
1098
+ return /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, "$", spend.toFixed(2), /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { component: "span", variant: "caption", sx: { ml: 0.5, opacity: 0.7 } }, "/ \u221E"));
1050
1099
  }
1051
1100
  const pct = Math.min(100, spend / maxBudget * 100);
1052
- return /* @__PURE__ */ import_react3.default.createElement(import_Box3.default, { minWidth: 104 }, /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums", mb: 0.5 } }, "$", spend.toFixed(2), /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { component: "span", variant: "caption", color: "text.secondary", sx: { ml: 0.5 } }, "/ $", maxBudget)), /* @__PURE__ */ import_react3.default.createElement(Meter, { value: pct, tone: budgetTone(pct), height: 4 }));
1101
+ return /* @__PURE__ */ import_react4.default.createElement(import_Box3.default, { minWidth: 104 }, /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums", mb: 0.5 } }, "$", spend.toFixed(2), /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { component: "span", variant: "caption", color: "text.secondary", sx: { ml: 0.5 } }, "/ $", maxBudget)), /* @__PURE__ */ import_react4.default.createElement(Meter, { value: pct, tone: budgetTone(pct), height: 4 }));
1053
1102
  }
1054
1103
  function compareKeys(a, b, sortKey) {
1055
1104
  switch (sortKey) {
@@ -1069,11 +1118,11 @@ function compareKeys(a, b, sortKey) {
1069
1118
  return 0;
1070
1119
  }
1071
1120
  }
1072
- var import_react3, import_Table, import_TableBody, import_TableCell, import_TableContainer, import_TableHead, import_TableRow, import_TableSortLabel, import_Button2, import_IconButton, import_Box3, import_Typography3, import_Dialog, import_DialogTitle, import_DialogContent, import_DialogActions, import_TextField, import_CircularProgress, import_Skeleton2, import_InputAdornment, import_styles3, import_icons_material2, shortKeyId, formatDate, KeysTable;
1121
+ var import_react4, import_Table, import_TableBody, import_TableCell, import_TableContainer, import_TableHead, import_TableRow, import_TableSortLabel, import_Button2, import_IconButton, import_Box3, import_Typography3, import_Dialog, import_DialogTitle, import_DialogContent, import_DialogActions, import_TextField, import_CircularProgress, import_Skeleton2, import_InputAdornment, import_styles3, import_icons_material2, shortKeyId, formatDate, KeysTable;
1073
1122
  var init_KeysTable = __esm({
1074
1123
  "src/components/KeysTable.tsx"() {
1075
1124
  "use strict";
1076
- import_react3 = __toESM(require("react"));
1125
+ import_react4 = __toESM(require("react"));
1077
1126
  import_Table = __toESM(require("@mui/material/Table"));
1078
1127
  import_TableBody = __toESM(require("@mui/material/TableBody"));
1079
1128
  import_TableCell = __toESM(require("@mui/material/TableCell"));
@@ -1096,6 +1145,7 @@ var init_KeysTable = __esm({
1096
1145
  import_styles3 = require("@mui/material/styles");
1097
1146
  import_icons_material2 = require("@mui/icons-material");
1098
1147
  init_api();
1148
+ init_GenerateKeyButton();
1099
1149
  init_ui();
1100
1150
  shortKeyId = (token) => {
1101
1151
  if (!token) return "-";
@@ -1119,12 +1169,12 @@ var init_KeysTable = __esm({
1119
1169
  onDeleteKey,
1120
1170
  onPruneExpiredKeys
1121
1171
  }) => {
1122
- const [blockingKeyId, setBlockingKeyId] = (0, import_react3.useState)(null);
1123
- const [deleteConfirmId, setDeleteConfirmId] = (0, import_react3.useState)(null);
1124
- const [deleteSubmitting, setDeleteSubmitting] = (0, import_react3.useState)(false);
1125
- const [filterText, setFilterText] = (0, import_react3.useState)("");
1126
- const [sortKey, setSortKey] = (0, import_react3.useState)("created");
1127
- const [sortDirection, setSortDirection] = (0, import_react3.useState)("desc");
1172
+ const [blockingKeyId, setBlockingKeyId] = (0, import_react4.useState)(null);
1173
+ const [deleteConfirmId, setDeleteConfirmId] = (0, import_react4.useState)(null);
1174
+ const [deleteSubmitting, setDeleteSubmitting] = (0, import_react4.useState)(false);
1175
+ const [filterText, setFilterText] = (0, import_react4.useState)("");
1176
+ const [sortKey, setSortKey] = (0, import_react4.useState)("created");
1177
+ const [sortDirection, setSortDirection] = (0, import_react4.useState)("desc");
1128
1178
  const handleSort = (nextSortKey) => {
1129
1179
  if (sortKey === nextSortKey) {
1130
1180
  setSortDirection((current) => current === "asc" ? "desc" : "asc");
@@ -1133,7 +1183,7 @@ var init_KeysTable = __esm({
1133
1183
  setSortDirection("asc");
1134
1184
  }
1135
1185
  };
1136
- const filteredKeys = (0, import_react3.useMemo)(() => {
1186
+ const filteredKeys = (0, import_react4.useMemo)(() => {
1137
1187
  let result = keys;
1138
1188
  if (filterText.trim()) {
1139
1189
  const q = filterText.toLowerCase();
@@ -1175,9 +1225,9 @@ var init_KeysTable = __esm({
1175
1225
  const copyToClipboard = (text) => {
1176
1226
  navigator.clipboard.writeText(text);
1177
1227
  };
1178
- const [pruneConfirmCount, setPruneConfirmCount] = (0, import_react3.useState)(null);
1179
- const [pruneSubmitting, setPruneSubmitting] = (0, import_react3.useState)(false);
1180
- const expiredKeys = (0, import_react3.useMemo)(() => {
1228
+ const [pruneConfirmCount, setPruneConfirmCount] = (0, import_react4.useState)(null);
1229
+ const [pruneSubmitting, setPruneSubmitting] = (0, import_react4.useState)(false);
1230
+ const expiredKeys = (0, import_react4.useMemo)(() => {
1181
1231
  return keys.filter((k) => expiryStatus(k.expires_at) === "expired");
1182
1232
  }, [keys]);
1183
1233
  const handlePruneExpired = async () => {
@@ -1194,32 +1244,27 @@ var init_KeysTable = __esm({
1194
1244
  };
1195
1245
  const renderTableBody = () => {
1196
1246
  if (loading) {
1197
- return /* @__PURE__ */ import_react3.default.createElement(import_TableRow.default, null, /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { colSpan: 8, sx: { py: 2 } }, /* @__PURE__ */ import_react3.default.createElement(import_Skeleton2.default, { variant: "rounded", height: 140 })));
1247
+ return /* @__PURE__ */ import_react4.default.createElement(import_TableRow.default, null, /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { colSpan: 8, sx: { py: 2 } }, /* @__PURE__ */ import_react4.default.createElement(import_Skeleton2.default, { variant: "rounded", height: 140 })));
1198
1248
  }
1199
1249
  if (filteredKeys.length === 0) {
1200
- return /* @__PURE__ */ import_react3.default.createElement(import_TableRow.default, null, /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { colSpan: 8 }, filterText ? /* @__PURE__ */ import_react3.default.createElement(
1250
+ return /* @__PURE__ */ import_react4.default.createElement(import_TableRow.default, null, /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { colSpan: 8 }, filterText ? /* @__PURE__ */ import_react4.default.createElement(
1201
1251
  EmptyState,
1202
1252
  {
1203
1253
  message: "No keys match that filter",
1204
1254
  hint: "Try a different alias or model name."
1205
1255
  }
1206
- ) : /* @__PURE__ */ import_react3.default.createElement(
1256
+ ) : /* @__PURE__ */ import_react4.default.createElement(
1207
1257
  EmptyState,
1208
1258
  {
1209
1259
  message: "No keys yet",
1210
1260
  hint: "Generate your first key to start calling models.",
1211
- action: /* @__PURE__ */ import_react3.default.createElement(
1212
- import_Button2.default,
1261
+ action: /* @__PURE__ */ import_react4.default.createElement(
1262
+ GenerateKeyButton,
1213
1263
  {
1214
- variant: "contained",
1215
- color: "primary",
1216
1264
  size: "small",
1217
- disableElevation: true,
1218
- startIcon: /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Add, null),
1219
- onClick: onGenerateKeyClick,
1220
- sx: { mt: 1 }
1221
- },
1222
- "Generate Your First Key"
1265
+ label: "Generate Your First Key",
1266
+ onClick: onGenerateKeyClick
1267
+ }
1223
1268
  )
1224
1269
  }
1225
1270
  )));
@@ -1228,7 +1273,7 @@ var init_KeysTable = __esm({
1228
1273
  const keyId = key.token ?? key.key;
1229
1274
  const isBlocking = blockingKeyId === keyId;
1230
1275
  const keyModels = key.models ?? [];
1231
- return /* @__PURE__ */ import_react3.default.createElement(
1276
+ return /* @__PURE__ */ import_react4.default.createElement(
1232
1277
  import_TableRow.default,
1233
1278
  {
1234
1279
  key: keyId,
@@ -1239,8 +1284,8 @@ var init_KeysTable = __esm({
1239
1284
  "& td": { color: theme.palette.text.secondary }
1240
1285
  }) : void 0
1241
1286
  },
1242
- /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Box3.default, { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { variant: "body2" }, key.key_alias || "\u2014"), key.blocked && /* @__PURE__ */ import_react3.default.createElement(StatusPill, { label: "Blocked", tone: "danger" }))),
1243
- /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Box3.default, { display: "flex", alignItems: "center", gap: 0.5 }, /* @__PURE__ */ import_react3.default.createElement(
1287
+ /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Box3.default, { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { variant: "body2" }, key.key_alias || "\u2014"), key.blocked && /* @__PURE__ */ import_react4.default.createElement(StatusPill, { label: "Blocked", tone: "danger" }))),
1288
+ /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Box3.default, { display: "flex", alignItems: "center", gap: 0.5 }, /* @__PURE__ */ import_react4.default.createElement(
1244
1289
  import_Typography3.default,
1245
1290
  {
1246
1291
  variant: "body2",
@@ -1257,7 +1302,7 @@ var init_KeysTable = __esm({
1257
1302
  })
1258
1303
  },
1259
1304
  shortKeyId(keyId)
1260
- ), /* @__PURE__ */ import_react3.default.createElement(
1305
+ ), /* @__PURE__ */ import_react4.default.createElement(
1261
1306
  import_IconButton.default,
1262
1307
  {
1263
1308
  size: "small",
@@ -1265,13 +1310,13 @@ var init_KeysTable = __esm({
1265
1310
  title: "Copy Key ID",
1266
1311
  sx: quietIconButtonSx("accent")
1267
1312
  },
1268
- /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.ContentCopy, { sx: { fontSize: 15 } })
1313
+ /* @__PURE__ */ import_react4.default.createElement(import_icons_material2.ContentCopy, { sx: { fontSize: 15 } })
1269
1314
  ))),
1270
- /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary" }, formatDate(key.created_at))),
1271
- /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react3.default.createElement(ExpiryCell, { expiresAt: key.expires_at })),
1272
- /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react3.default.createElement(BudgetCell, { spend: key.spend ?? 0, maxBudget: key.max_budget })),
1273
- /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, key.tpm_limit ?? "\u221E", " / ", key.rpm_limit ?? "\u221E")),
1274
- /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, null, keyModels.length === 0 ? /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary" }, "All models") : /* @__PURE__ */ import_react3.default.createElement(import_Box3.default, { display: "flex", gap: 0.5, flexWrap: "wrap" }, keyModels.slice(0, 2).map((model) => /* @__PURE__ */ import_react3.default.createElement(TagChip, { key: model, label: model, title: model })), keyModels.length > 2 && /* @__PURE__ */ import_react3.default.createElement(
1315
+ /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary" }, formatDate(key.created_at))),
1316
+ /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react4.default.createElement(ExpiryCell, { expiresAt: key.expires_at })),
1317
+ /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react4.default.createElement(BudgetCell, { spend: key.spend ?? 0, maxBudget: key.max_budget })),
1318
+ /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, key.tpm_limit ?? "\u221E", " / ", key.rpm_limit ?? "\u221E")),
1319
+ /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, null, keyModels.length === 0 ? /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, { variant: "body2", color: "text.secondary" }, "All models") : /* @__PURE__ */ import_react4.default.createElement(import_Box3.default, { display: "flex", gap: 0.5, flexWrap: "wrap" }, keyModels.slice(0, 2).map((model) => /* @__PURE__ */ import_react4.default.createElement(TagChip, { key: model, label: model, title: model })), keyModels.length > 2 && /* @__PURE__ */ import_react4.default.createElement(
1275
1320
  TagChip,
1276
1321
  {
1277
1322
  label: `+${keyModels.length - 2}`,
@@ -1279,7 +1324,7 @@ var init_KeysTable = __esm({
1279
1324
  title: keyModels.slice(2).join(", ")
1280
1325
  }
1281
1326
  ))),
1282
- /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { align: "right" }, /* @__PURE__ */ import_react3.default.createElement(import_Box3.default, { display: "flex", justifyContent: "flex-end", gap: 0.25 }, /* @__PURE__ */ import_react3.default.createElement(
1327
+ /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { align: "right" }, /* @__PURE__ */ import_react4.default.createElement(import_Box3.default, { display: "flex", justifyContent: "flex-end", gap: 0.25 }, /* @__PURE__ */ import_react4.default.createElement(
1283
1328
  import_IconButton.default,
1284
1329
  {
1285
1330
  size: "small",
@@ -1287,8 +1332,8 @@ var init_KeysTable = __esm({
1287
1332
  title: "Edit key",
1288
1333
  sx: quietIconButtonSx("accent")
1289
1334
  },
1290
- /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Edit, { fontSize: "small" })
1291
- ), /* @__PURE__ */ import_react3.default.createElement(
1335
+ /* @__PURE__ */ import_react4.default.createElement(import_icons_material2.Edit, { fontSize: "small" })
1336
+ ), /* @__PURE__ */ import_react4.default.createElement(
1292
1337
  import_IconButton.default,
1293
1338
  {
1294
1339
  size: "small",
@@ -1298,7 +1343,7 @@ var init_KeysTable = __esm({
1298
1343
  sx: quietIconButtonSx("warning")
1299
1344
  },
1300
1345
  keyBlockIcon(isBlocking, key.blocked)
1301
- ), /* @__PURE__ */ import_react3.default.createElement(
1346
+ ), /* @__PURE__ */ import_react4.default.createElement(
1302
1347
  import_IconButton.default,
1303
1348
  {
1304
1349
  size: "small",
@@ -1306,18 +1351,18 @@ var init_KeysTable = __esm({
1306
1351
  title: "Revoke key",
1307
1352
  sx: quietIconButtonSx("danger")
1308
1353
  },
1309
- /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Delete, { fontSize: "small" })
1354
+ /* @__PURE__ */ import_react4.default.createElement(import_icons_material2.Delete, { fontSize: "small" })
1310
1355
  )))
1311
1356
  );
1312
1357
  });
1313
1358
  };
1314
- return /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement(
1359
+ return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement(
1315
1360
  SectionCard,
1316
1361
  {
1317
1362
  title: "Virtual Keys",
1318
1363
  subtitle: loading ? "Loading\u2026" : `${filteredKeys.length}${filterText ? ` of ${keys.length}` : ""} key${filteredKeys.length === 1 ? "" : "s"}`,
1319
1364
  flush: true,
1320
- actions: /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement(
1365
+ actions: /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement(
1321
1366
  import_TextField.default,
1322
1367
  {
1323
1368
  size: "small",
@@ -1327,15 +1372,15 @@ var init_KeysTable = __esm({
1327
1372
  onChange: (e) => setFilterText(e.target.value),
1328
1373
  sx: { minWidth: 240 },
1329
1374
  InputProps: {
1330
- startAdornment: /* @__PURE__ */ import_react3.default.createElement(import_InputAdornment.default, { position: "start" }, /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Search, { fontSize: "small", color: "disabled" }))
1375
+ startAdornment: /* @__PURE__ */ import_react4.default.createElement(import_InputAdornment.default, { position: "start" }, /* @__PURE__ */ import_react4.default.createElement(import_icons_material2.Search, { fontSize: "small", color: "disabled" }))
1331
1376
  }
1332
1377
  }
1333
- ), expiredKeys.length > 0 && /* @__PURE__ */ import_react3.default.createElement(
1378
+ ), expiredKeys.length > 0 && /* @__PURE__ */ import_react4.default.createElement(
1334
1379
  import_Button2.default,
1335
1380
  {
1336
1381
  variant: "outlined",
1337
1382
  color: "inherit",
1338
- startIcon: /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Autorenew, null),
1383
+ startIcon: /* @__PURE__ */ import_react4.default.createElement(import_icons_material2.Autorenew, null),
1339
1384
  onClick: () => setPruneConfirmCount(expiredKeys.length),
1340
1385
  sx: (theme) => ({
1341
1386
  color: theme.palette.text.secondary,
@@ -1350,20 +1395,10 @@ var init_KeysTable = __esm({
1350
1395
  "Prune expired (",
1351
1396
  expiredKeys.length,
1352
1397
  ")"
1353
- ), /* @__PURE__ */ import_react3.default.createElement(
1354
- import_Button2.default,
1355
- {
1356
- variant: "contained",
1357
- color: "primary",
1358
- disableElevation: true,
1359
- startIcon: /* @__PURE__ */ import_react3.default.createElement(import_icons_material2.Add, null),
1360
- onClick: onGenerateKeyClick
1361
- },
1362
- "Generate New Key"
1363
- ))
1398
+ ), /* @__PURE__ */ import_react4.default.createElement(GenerateKeyButton, { onClick: onGenerateKeyClick }))
1364
1399
  },
1365
- /* @__PURE__ */ import_react3.default.createElement(import_TableContainer.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Table.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react3.default.createElement(import_TableHead.default, null, /* @__PURE__ */ import_react3.default.createElement(import_TableRow.default, null, /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { sortDirection: sortKey === "alias" ? sortDirection : false }, /* @__PURE__ */ import_react3.default.createElement(import_TableSortLabel.default, { active: sortKey === "alias", direction: sortKey === "alias" ? sortDirection : "asc", onClick: () => handleSort("alias") }, "Alias")), /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, null, "Key ID"), /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { sortDirection: sortKey === "created" ? sortDirection : false }, /* @__PURE__ */ import_react3.default.createElement(import_TableSortLabel.default, { active: sortKey === "created", direction: sortKey === "created" ? sortDirection : "asc", onClick: () => handleSort("created") }, "Created")), /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { sortDirection: sortKey === "expires" ? sortDirection : false }, /* @__PURE__ */ import_react3.default.createElement(import_TableSortLabel.default, { active: sortKey === "expires", direction: sortKey === "expires" ? sortDirection : "asc", onClick: () => handleSort("expires") }, "Expires")), /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { sortDirection: sortKey === "budget" ? sortDirection : false }, /* @__PURE__ */ import_react3.default.createElement(import_TableSortLabel.default, { active: sortKey === "budget", direction: sortKey === "budget" ? sortDirection : "asc", onClick: () => handleSort("budget") }, "Budget")), /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { sortDirection: sortKey === "limits" ? sortDirection : false }, /* @__PURE__ */ import_react3.default.createElement(import_TableSortLabel.default, { active: sortKey === "limits", direction: sortKey === "limits" ? sortDirection : "asc", onClick: () => handleSort("limits") }, "TPM / RPM")), /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { sortDirection: sortKey === "models" ? sortDirection : false }, /* @__PURE__ */ import_react3.default.createElement(import_TableSortLabel.default, { active: sortKey === "models", direction: sortKey === "models" ? sortDirection : "asc", onClick: () => handleSort("models") }, "Models")), /* @__PURE__ */ import_react3.default.createElement(import_TableCell.default, { align: "right" }, "Actions"))), /* @__PURE__ */ import_react3.default.createElement(import_TableBody.default, null, renderTableBody())))
1366
- ), /* @__PURE__ */ import_react3.default.createElement(import_Dialog.default, { open: !!deleteConfirmId, onClose: () => setDeleteConfirmId(null), maxWidth: "xs", fullWidth: true }, /* @__PURE__ */ import_react3.default.createElement(import_DialogTitle.default, null, "Revoke Key?"), /* @__PURE__ */ import_react3.default.createElement(import_DialogContent.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, null, "This will permanently revoke the key. Any integrations using it will stop working immediately.")), /* @__PURE__ */ import_react3.default.createElement(import_DialogActions.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Button2.default, { onClick: () => setDeleteConfirmId(null), disabled: deleteSubmitting }, "Cancel"), /* @__PURE__ */ import_react3.default.createElement(
1400
+ /* @__PURE__ */ import_react4.default.createElement(import_TableContainer.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Table.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react4.default.createElement(import_TableHead.default, null, /* @__PURE__ */ import_react4.default.createElement(import_TableRow.default, null, /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { sortDirection: sortKey === "alias" ? sortDirection : false }, /* @__PURE__ */ import_react4.default.createElement(import_TableSortLabel.default, { active: sortKey === "alias", direction: sortKey === "alias" ? sortDirection : "asc", onClick: () => handleSort("alias") }, "Alias")), /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, null, "Key ID"), /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { sortDirection: sortKey === "created" ? sortDirection : false }, /* @__PURE__ */ import_react4.default.createElement(import_TableSortLabel.default, { active: sortKey === "created", direction: sortKey === "created" ? sortDirection : "asc", onClick: () => handleSort("created") }, "Created")), /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { sortDirection: sortKey === "expires" ? sortDirection : false }, /* @__PURE__ */ import_react4.default.createElement(import_TableSortLabel.default, { active: sortKey === "expires", direction: sortKey === "expires" ? sortDirection : "asc", onClick: () => handleSort("expires") }, "Expires")), /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { sortDirection: sortKey === "budget" ? sortDirection : false }, /* @__PURE__ */ import_react4.default.createElement(import_TableSortLabel.default, { active: sortKey === "budget", direction: sortKey === "budget" ? sortDirection : "asc", onClick: () => handleSort("budget") }, "Budget")), /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { sortDirection: sortKey === "limits" ? sortDirection : false }, /* @__PURE__ */ import_react4.default.createElement(import_TableSortLabel.default, { active: sortKey === "limits", direction: sortKey === "limits" ? sortDirection : "asc", onClick: () => handleSort("limits") }, "TPM / RPM")), /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { sortDirection: sortKey === "models" ? sortDirection : false }, /* @__PURE__ */ import_react4.default.createElement(import_TableSortLabel.default, { active: sortKey === "models", direction: sortKey === "models" ? sortDirection : "asc", onClick: () => handleSort("models") }, "Models")), /* @__PURE__ */ import_react4.default.createElement(import_TableCell.default, { align: "right" }, "Actions"))), /* @__PURE__ */ import_react4.default.createElement(import_TableBody.default, null, renderTableBody())))
1401
+ ), /* @__PURE__ */ import_react4.default.createElement(import_Dialog.default, { open: !!deleteConfirmId, onClose: () => setDeleteConfirmId(null), maxWidth: "xs", fullWidth: true }, /* @__PURE__ */ import_react4.default.createElement(import_DialogTitle.default, null, "Revoke Key?"), /* @__PURE__ */ import_react4.default.createElement(import_DialogContent.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, null, "This will permanently revoke the key. Any integrations using it will stop working immediately.")), /* @__PURE__ */ import_react4.default.createElement(import_DialogActions.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Button2.default, { onClick: () => setDeleteConfirmId(null), disabled: deleteSubmitting }, "Cancel"), /* @__PURE__ */ import_react4.default.createElement(
1367
1402
  import_Button2.default,
1368
1403
  {
1369
1404
  onClick: handleConfirmDelete,
@@ -1371,8 +1406,8 @@ var init_KeysTable = __esm({
1371
1406
  color: "error",
1372
1407
  disabled: deleteSubmitting
1373
1408
  },
1374
- deleteSubmitting ? /* @__PURE__ */ import_react3.default.createElement(import_CircularProgress.default, { size: 20 }) : "Revoke"
1375
- ))), /* @__PURE__ */ import_react3.default.createElement(import_Dialog.default, { open: pruneConfirmCount !== null, onClose: () => setPruneConfirmCount(null), maxWidth: "xs", fullWidth: true }, /* @__PURE__ */ import_react3.default.createElement(import_DialogTitle.default, null, "Prune Expired Keys?"), /* @__PURE__ */ import_react3.default.createElement(import_DialogContent.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Typography3.default, null, "This will permanently delete ", pruneConfirmCount, " expired key", pruneConfirmCount !== 1 ? "s" : "", " from LiteLLM. Any integrations using them will stop working immediately.")), /* @__PURE__ */ import_react3.default.createElement(import_DialogActions.default, null, /* @__PURE__ */ import_react3.default.createElement(import_Button2.default, { onClick: () => setPruneConfirmCount(null), disabled: pruneSubmitting }, "Cancel"), /* @__PURE__ */ import_react3.default.createElement(
1409
+ deleteSubmitting ? /* @__PURE__ */ import_react4.default.createElement(import_CircularProgress.default, { size: 20 }) : "Revoke"
1410
+ ))), /* @__PURE__ */ import_react4.default.createElement(import_Dialog.default, { open: pruneConfirmCount !== null, onClose: () => setPruneConfirmCount(null), maxWidth: "xs", fullWidth: true }, /* @__PURE__ */ import_react4.default.createElement(import_DialogTitle.default, null, "Prune Expired Keys?"), /* @__PURE__ */ import_react4.default.createElement(import_DialogContent.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Typography3.default, null, "This will permanently delete ", pruneConfirmCount, " expired key", pruneConfirmCount !== 1 ? "s" : "", " from LiteLLM. Any integrations using them will stop working immediately.")), /* @__PURE__ */ import_react4.default.createElement(import_DialogActions.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Button2.default, { onClick: () => setPruneConfirmCount(null), disabled: pruneSubmitting }, "Cancel"), /* @__PURE__ */ import_react4.default.createElement(
1376
1411
  import_Button2.default,
1377
1412
  {
1378
1413
  onClick: handlePruneExpired,
@@ -1380,7 +1415,7 @@ var init_KeysTable = __esm({
1380
1415
  color: "error",
1381
1416
  disabled: pruneSubmitting
1382
1417
  },
1383
- pruneSubmitting ? /* @__PURE__ */ import_react3.default.createElement(import_CircularProgress.default, { size: 20 }) : "Prune"
1418
+ pruneSubmitting ? /* @__PURE__ */ import_react4.default.createElement(import_CircularProgress.default, { size: 20 }) : "Prune"
1384
1419
  ))));
1385
1420
  };
1386
1421
  }
@@ -1518,11 +1553,11 @@ function formatContextWindow(maxInput, maxOutput) {
1518
1553
  if (outPart) return `ctx ${outPart} out`;
1519
1554
  return null;
1520
1555
  }
1521
- var import_react4, import_Box4, import_Typography4, import_Dialog2, import_DialogTitle2, import_DialogContent2, import_DialogActions2, import_TextField2, import_MenuItem, import_Button3, import_IconButton2, import_CircularProgress2, import_Autocomplete, import_Checkbox, import_FormControlLabel, import_Alert, import_Accordion, import_AccordionSummary, import_AccordionDetails, import_Tabs, import_Tab, import_icons_material3, generateDefaultAlias, createForm, editForm, ALL_PROXY_MODELS, SNIPPET_FILE_HINTS, SnippetTabs, KeyFormDialog;
1556
+ var import_react5, import_Box4, import_Typography4, import_Dialog2, import_DialogTitle2, import_DialogContent2, import_DialogActions2, import_TextField2, import_MenuItem, import_Button3, import_IconButton2, import_CircularProgress2, import_Autocomplete, import_Checkbox, import_FormControlLabel, import_Alert, import_Accordion, import_AccordionSummary, import_AccordionDetails, import_Tabs, import_Tab, import_icons_material3, generateDefaultAlias, createForm, editForm, ALL_PROXY_MODELS, SNIPPET_FILE_HINTS, SnippetTabs, KeyFormDialog;
1522
1557
  var init_KeyFormDialog = __esm({
1523
1558
  "src/components/KeyFormDialog.tsx"() {
1524
1559
  "use strict";
1525
- import_react4 = __toESM(require("react"));
1560
+ import_react5 = __toESM(require("react"));
1526
1561
  import_Box4 = __toESM(require("@mui/material/Box"));
1527
1562
  import_Typography4 = __toESM(require("@mui/material/Typography"));
1528
1563
  import_Dialog2 = __toESM(require("@mui/material/Dialog"));
@@ -1574,18 +1609,18 @@ var init_KeyFormDialog = __esm({
1574
1609
  "claude-code": "Requires Claude Code CLI installed"
1575
1610
  };
1576
1611
  SnippetTabs = ({ snippets, model, onCopy }) => {
1577
- const [tab, setTab] = (0, import_react4.useState)("curl");
1612
+ const [tab, setTab] = (0, import_react5.useState)("curl");
1578
1613
  const snippetKey = tab === "claude-code" ? "claudeCode" : tab;
1579
1614
  const code = snippets[snippetKey];
1580
1615
  const fileHint = SNIPPET_FILE_HINTS[tab];
1581
- return /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Tabs.default, { value: tab, onChange: (_, v) => setTab(v), sx: { mb: 1 }, variant: "scrollable" }, /* @__PURE__ */ import_react4.default.createElement(import_Tab.default, { label: "curl", value: "curl" }), /* @__PURE__ */ import_react4.default.createElement(import_Tab.default, { label: "OpenAI SDK", value: "openai" }), /* @__PURE__ */ import_react4.default.createElement(import_Tab.default, { label: "opencode", value: "opencode" }), /* @__PURE__ */ import_react4.default.createElement(import_Tab.default, { label: "pi", value: "pi" }), /* @__PURE__ */ import_react4.default.createElement(import_Tab.default, { label: "Claude Code", value: "claude-code" })), fileHint && /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", display: "block", mb: 0.5 }, fileHint), /* @__PURE__ */ import_react4.default.createElement(
1616
+ return /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, null, /* @__PURE__ */ import_react5.default.createElement(import_Tabs.default, { value: tab, onChange: (_, v) => setTab(v), sx: { mb: 1 }, variant: "scrollable" }, /* @__PURE__ */ import_react5.default.createElement(import_Tab.default, { label: "curl", value: "curl" }), /* @__PURE__ */ import_react5.default.createElement(import_Tab.default, { label: "OpenAI SDK", value: "openai" }), /* @__PURE__ */ import_react5.default.createElement(import_Tab.default, { label: "opencode", value: "opencode" }), /* @__PURE__ */ import_react5.default.createElement(import_Tab.default, { label: "pi", value: "pi" }), /* @__PURE__ */ import_react5.default.createElement(import_Tab.default, { label: "Claude Code", value: "claude-code" })), fileHint && /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", display: "block", mb: 0.5 }, fileHint), /* @__PURE__ */ import_react5.default.createElement(
1582
1617
  import_Box4.default,
1583
1618
  {
1584
1619
  position: "relative",
1585
1620
  p: 1.5,
1586
1621
  sx: { backgroundColor: "action.hover", border: "1px solid", borderColor: "divider", borderRadius: 1 }
1587
1622
  },
1588
- /* @__PURE__ */ import_react4.default.createElement(
1623
+ /* @__PURE__ */ import_react5.default.createElement(
1589
1624
  import_IconButton2.default,
1590
1625
  {
1591
1626
  size: "small",
@@ -1593,9 +1628,9 @@ var init_KeyFormDialog = __esm({
1593
1628
  title: "Copy snippet",
1594
1629
  sx: { position: "absolute", top: 4, right: 4 }
1595
1630
  },
1596
- /* @__PURE__ */ import_react4.default.createElement(import_icons_material3.ContentCopy, { fontSize: "small" })
1631
+ /* @__PURE__ */ import_react5.default.createElement(import_icons_material3.ContentCopy, { fontSize: "small" })
1597
1632
  ),
1598
- /* @__PURE__ */ import_react4.default.createElement(
1633
+ /* @__PURE__ */ import_react5.default.createElement(
1599
1634
  import_Typography4.default,
1600
1635
  {
1601
1636
  component: "pre",
@@ -1610,7 +1645,7 @@ var init_KeyFormDialog = __esm({
1610
1645
  },
1611
1646
  code
1612
1647
  ),
1613
- model && /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", display: "block", mt: 1 }, "Using model \u201C", model, "\u201D \u2014 swap it for any model you have access to.")
1648
+ model && /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", display: "block", mt: 1 }, "Using model \u201C", model, "\u201D \u2014 swap it for any model you have access to.")
1614
1649
  ));
1615
1650
  };
1616
1651
  KeyFormDialog = ({
@@ -1629,18 +1664,18 @@ var init_KeyFormDialog = __esm({
1629
1664
  onGetConfig
1630
1665
  }) => {
1631
1666
  const isCreate = mode === "create";
1632
- const [generateForm, setGenerateForm] = (0, import_react4.useState)(createForm(username));
1633
- const [editFormState, setEditFormState] = (0, import_react4.useState)({});
1634
- const [unlimitedBudget, setUnlimitedBudget] = (0, import_react4.useState)(false);
1635
- const [submitting, setSubmitting] = (0, import_react4.useState)(false);
1636
- const [newKeyValue, setNewKeyValue] = (0, import_react4.useState)(null);
1637
- const [newKeySnippets, setNewKeySnippets] = (0, import_react4.useState)(null);
1638
- const [newKeyModel, setNewKeyModel] = (0, import_react4.useState)("");
1639
- const [generateError, setGenerateError] = (0, import_react4.useState)(null);
1640
- const [editError, setEditError] = (0, import_react4.useState)(null);
1641
- const [resetSpendConfirm, setResetSpendConfirm] = (0, import_react4.useState)(false);
1642
- const [resetSpendSubmitting, setResetSpendSubmitting] = (0, import_react4.useState)(false);
1643
- (0, import_react4.useEffect)(() => {
1667
+ const [generateForm, setGenerateForm] = (0, import_react5.useState)(createForm(username));
1668
+ const [editFormState, setEditFormState] = (0, import_react5.useState)({});
1669
+ const [unlimitedBudget, setUnlimitedBudget] = (0, import_react5.useState)(false);
1670
+ const [submitting, setSubmitting] = (0, import_react5.useState)(false);
1671
+ const [newKeyValue, setNewKeyValue] = (0, import_react5.useState)(null);
1672
+ const [newKeySnippets, setNewKeySnippets] = (0, import_react5.useState)(null);
1673
+ const [newKeyModel, setNewKeyModel] = (0, import_react5.useState)("");
1674
+ const [generateError, setGenerateError] = (0, import_react5.useState)(null);
1675
+ const [editError, setEditError] = (0, import_react5.useState)(null);
1676
+ const [resetSpendConfirm, setResetSpendConfirm] = (0, import_react5.useState)(false);
1677
+ const [resetSpendSubmitting, setResetSpendSubmitting] = (0, import_react5.useState)(false);
1678
+ (0, import_react5.useEffect)(() => {
1644
1679
  if (open) {
1645
1680
  if (isCreate) {
1646
1681
  setGenerateForm(createForm(username));
@@ -1677,7 +1712,7 @@ var init_KeyFormDialog = __esm({
1677
1712
  else setFormData({ key_alias: value });
1678
1713
  };
1679
1714
  const selectedTeam = teams.find((t) => t.team_id === (isCreate ? generateForm.team_id : void 0)) ?? null;
1680
- const availableModels = (0, import_react4.useMemo)(() => {
1715
+ const availableModels = (0, import_react5.useMemo)(() => {
1681
1716
  return models.filter((m) => isModelAllowedByTeam(m, selectedTeam?.models));
1682
1717
  }, [models, selectedTeam]);
1683
1718
  const selectedModels = availableModels.filter((m) => (formData.models || []).includes(m.model_name));
@@ -1686,7 +1721,7 @@ var init_KeyFormDialog = __esm({
1686
1721
  const budgetInvalid = !unlimitedBudget && (formData.max_budget === void 0 || formData.max_budget === null || formData.max_budget <= 0);
1687
1722
  const canSubmit = !aliasError && !teamError && !budgetInvalid && !submitting;
1688
1723
  const aliasDuplicate = !!currentAlias && keys.some((k) => k.key_alias === currentAlias && k !== keyToEdit);
1689
- const budgetEstimate = (0, import_react4.useMemo)(() => {
1724
+ const budgetEstimate = (0, import_react5.useMemo)(() => {
1690
1725
  if (unlimitedBudget || budgetInvalid) return null;
1691
1726
  const inputCosts = selectedModels.map((m) => m.input_cost_per_token).filter((c) => typeof c === "number" && c > 0);
1692
1727
  if (inputCosts.length === 0) return null;
@@ -1765,11 +1800,11 @@ var init_KeyFormDialog = __esm({
1765
1800
  const inCost = fmtCost(m.input_cost_per_token);
1766
1801
  const outCost = fmtCost(m.output_cost_per_token);
1767
1802
  const ctx = formatContextWindow(m.max_input_tokens, m.max_output_tokens);
1768
- return /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, null, /* @__PURE__ */ import_react4.default.createElement("span", null, m.model_name), m.supports_function_calling && " \u{1F527}", m.supports_vision && " \u{1F441}\uFE0F", ctx && /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", sx: { ml: 1 } }, ctx), (inCost || outCost) && /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", sx: { ml: 1 } }, inCost, " in \xB7 ", outCost, " out"));
1803
+ return /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, null, /* @__PURE__ */ import_react5.default.createElement("span", null, m.model_name), m.supports_function_calling && " \u{1F527}", m.supports_vision && " \u{1F441}\uFE0F", ctx && /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", sx: { ml: 1 } }, ctx), (inCost || outCost) && /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", sx: { ml: 1 } }, inCost, " in \xB7 ", outCost, " out"));
1769
1804
  };
1770
1805
  const renderTeamField = () => {
1771
1806
  if (teams.length > 0) {
1772
- return /* @__PURE__ */ import_react4.default.createElement(
1807
+ return /* @__PURE__ */ import_react5.default.createElement(
1773
1808
  import_Autocomplete.default,
1774
1809
  {
1775
1810
  options: teams,
@@ -1783,7 +1818,7 @@ var init_KeyFormDialog = __esm({
1783
1818
  setFormData({ team_id: team?.team_id, models: restrictedModels });
1784
1819
  },
1785
1820
  disabled: !isCreate,
1786
- renderInput: (params) => /* @__PURE__ */ import_react4.default.createElement(
1821
+ renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(
1787
1822
  import_TextField2.default,
1788
1823
  {
1789
1824
  ...params,
@@ -1798,14 +1833,14 @@ var init_KeyFormDialog = __esm({
1798
1833
  );
1799
1834
  }
1800
1835
  if (teamRequired && isCreate) {
1801
- return /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "body2", color: "error" }, "Team selection is required, but you don't belong to any team yet \u2014 contact your administrator.");
1836
+ return /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "body2", color: "error" }, "Team selection is required, but you don't belong to any team yet \u2014 contact your administrator.");
1802
1837
  }
1803
1838
  return null;
1804
1839
  };
1805
1840
  const editKeyId = keyToEdit?.token ?? keyToEdit?.key ?? "";
1806
1841
  const renderDangerZone = () => {
1807
1842
  if (isCreate || !onResetKeySpend) return null;
1808
- return /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, { mt: 1, pt: 2, borderTop: "1px solid", sx: { borderColor: "divider" } }, /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", display: "block", mb: 1 }, "Danger Zone"), !resetSpendConfirm ? /* @__PURE__ */ import_react4.default.createElement(
1843
+ return /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, { mt: 1, pt: 2, borderTop: "1px solid", sx: { borderColor: "divider" } }, /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", display: "block", mb: 1 }, "Danger Zone"), !resetSpendConfirm ? /* @__PURE__ */ import_react5.default.createElement(
1809
1844
  import_Button3.default,
1810
1845
  {
1811
1846
  size: "small",
@@ -1814,7 +1849,7 @@ var init_KeyFormDialog = __esm({
1814
1849
  onClick: () => setResetSpendConfirm(true)
1815
1850
  },
1816
1851
  "Reset Spend to $0"
1817
- ) : /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "body2", color: "warning.main" }, "Zero out spend counter?"), /* @__PURE__ */ import_react4.default.createElement(
1852
+ ) : /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "body2", color: "warning.main" }, "Zero out spend counter?"), /* @__PURE__ */ import_react5.default.createElement(
1818
1853
  import_Button3.default,
1819
1854
  {
1820
1855
  size: "small",
@@ -1823,8 +1858,8 @@ var init_KeyFormDialog = __esm({
1823
1858
  disabled: resetSpendSubmitting,
1824
1859
  onClick: handleResetSpend
1825
1860
  },
1826
- resetSpendSubmitting ? /* @__PURE__ */ import_react4.default.createElement(import_CircularProgress2.default, { size: 16 }) : "Confirm"
1827
- ), /* @__PURE__ */ import_react4.default.createElement(import_Button3.default, { size: "small", onClick: () => setResetSpendConfirm(false) }, "Cancel")));
1861
+ resetSpendSubmitting ? /* @__PURE__ */ import_react5.default.createElement(import_CircularProgress2.default, { size: 16 }) : "Confirm"
1862
+ ), /* @__PURE__ */ import_react5.default.createElement(import_Button3.default, { size: "small", onClick: () => setResetSpendConfirm(false) }, "Cancel")));
1828
1863
  };
1829
1864
  const maskKey = (key) => {
1830
1865
  if (key.length <= 8) return "***";
@@ -1834,7 +1869,7 @@ var init_KeyFormDialog = __esm({
1834
1869
  if (newKeyValue) dialogTitle = "Key Generated";
1835
1870
  else if (isCreate) dialogTitle = "Generate New Key";
1836
1871
  const submitLabel = isCreate ? "Generate" : "Save";
1837
- return /* @__PURE__ */ import_react4.default.createElement(import_Dialog2.default, { open, onClose: handleClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ import_react4.default.createElement(import_DialogTitle2.default, null, dialogTitle), /* @__PURE__ */ import_react4.default.createElement(import_DialogContent2.default, null, newKeyValue ? /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, null, /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "body2", color: "text.secondary", gutterBottom: true }, "Copy this key now. You won't be able to see it again."), /* @__PURE__ */ import_react4.default.createElement(
1872
+ return /* @__PURE__ */ import_react5.default.createElement(import_Dialog2.default, { open, onClose: handleClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ import_react5.default.createElement(import_DialogTitle2.default, null, dialogTitle), /* @__PURE__ */ import_react5.default.createElement(import_DialogContent2.default, null, newKeyValue ? /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, null, /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "body2", color: "text.secondary", gutterBottom: true }, "Copy this key now. You won't be able to see it again."), /* @__PURE__ */ import_react5.default.createElement(
1838
1873
  import_Box4.default,
1839
1874
  {
1840
1875
  display: "flex",
@@ -1849,7 +1884,7 @@ var init_KeyFormDialog = __esm({
1849
1884
  borderRadius: 1
1850
1885
  }
1851
1886
  },
1852
- /* @__PURE__ */ import_react4.default.createElement(
1887
+ /* @__PURE__ */ import_react5.default.createElement(
1853
1888
  import_Typography4.default,
1854
1889
  {
1855
1890
  component: "code",
@@ -1858,8 +1893,8 @@ var init_KeyFormDialog = __esm({
1858
1893
  },
1859
1894
  newKeyValue
1860
1895
  ),
1861
- /* @__PURE__ */ import_react4.default.createElement(import_IconButton2.default, { onClick: () => copyToClipboard(newKeyValue) }, /* @__PURE__ */ import_react4.default.createElement(import_icons_material3.ContentCopy, null))
1862
- ), newKeySnippets && /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, { mt: 2 }, /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", display: "block", gutterBottom: true }, "Public endpoint \u2014 paste into any tool's base URL / API base field"), /* @__PURE__ */ import_react4.default.createElement(
1896
+ /* @__PURE__ */ import_react5.default.createElement(import_IconButton2.default, { onClick: () => copyToClipboard(newKeyValue) }, /* @__PURE__ */ import_react5.default.createElement(import_icons_material3.ContentCopy, null))
1897
+ ), newKeySnippets && /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, { mt: 2 }, /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "caption", color: "text.secondary", display: "block", gutterBottom: true }, "Public endpoint \u2014 paste into any tool's base URL / API base field"), /* @__PURE__ */ import_react5.default.createElement(
1863
1898
  import_Box4.default,
1864
1899
  {
1865
1900
  display: "flex",
@@ -1873,7 +1908,7 @@ var init_KeyFormDialog = __esm({
1873
1908
  borderRadius: 1
1874
1909
  }
1875
1910
  },
1876
- /* @__PURE__ */ import_react4.default.createElement(
1911
+ /* @__PURE__ */ import_react5.default.createElement(
1877
1912
  import_Typography4.default,
1878
1913
  {
1879
1914
  component: "code",
@@ -1882,8 +1917,8 @@ var init_KeyFormDialog = __esm({
1882
1917
  },
1883
1918
  newKeySnippets.publicEndpoint
1884
1919
  ),
1885
- /* @__PURE__ */ import_react4.default.createElement(import_IconButton2.default, { size: "small", onClick: () => copyToClipboard(newKeySnippets.publicEndpoint) }, /* @__PURE__ */ import_react4.default.createElement(import_icons_material3.ContentCopy, { fontSize: "small" }))
1886
- )), newKeySnippets && /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, { mt: 3 }, /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, { display: "flex", alignItems: "center", gap: 1, mb: 1 }, /* @__PURE__ */ import_react4.default.createElement(import_icons_material3.Code, { fontSize: "small", color: "action" }), /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "subtitle2" }, "Start calling the proxy \u2014 paste and run")), /* @__PURE__ */ import_react4.default.createElement(SnippetTabs, { snippets: newKeySnippets, model: newKeyModel, onCopy: copyToClipboard }))) : /* @__PURE__ */ import_react4.default.createElement(import_Box4.default, { display: "flex", flexDirection: "column", gap: 2, mt: 1 }, !isCreate && /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "body2", color: "text.secondary" }, /* @__PURE__ */ import_react4.default.createElement("code", { style: { fontFamily: "monospace", color: "inherit" } }, maskKey(editKeyId))), generateError && /* @__PURE__ */ import_react4.default.createElement(import_Alert.default, { severity: "error", onClose: () => setGenerateError(null) }, generateError), editError && /* @__PURE__ */ import_react4.default.createElement(import_Alert.default, { severity: "error", onClose: () => setEditError(null) }, editError), /* @__PURE__ */ import_react4.default.createElement(
1920
+ /* @__PURE__ */ import_react5.default.createElement(import_IconButton2.default, { size: "small", onClick: () => copyToClipboard(newKeySnippets.publicEndpoint) }, /* @__PURE__ */ import_react5.default.createElement(import_icons_material3.ContentCopy, { fontSize: "small" }))
1921
+ )), newKeySnippets && /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, { mt: 3 }, /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, { display: "flex", alignItems: "center", gap: 1, mb: 1 }, /* @__PURE__ */ import_react5.default.createElement(import_icons_material3.Code, { fontSize: "small", color: "action" }), /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "subtitle2" }, "Start calling the proxy \u2014 paste and run")), /* @__PURE__ */ import_react5.default.createElement(SnippetTabs, { snippets: newKeySnippets, model: newKeyModel, onCopy: copyToClipboard }))) : /* @__PURE__ */ import_react5.default.createElement(import_Box4.default, { display: "flex", flexDirection: "column", gap: 2, mt: 1 }, !isCreate && /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "body2", color: "text.secondary" }, /* @__PURE__ */ import_react5.default.createElement("code", { style: { fontFamily: "monospace", color: "inherit" } }, maskKey(editKeyId))), generateError && /* @__PURE__ */ import_react5.default.createElement(import_Alert.default, { severity: "error", onClose: () => setGenerateError(null) }, generateError), editError && /* @__PURE__ */ import_react5.default.createElement(import_Alert.default, { severity: "error", onClose: () => setEditError(null) }, editError), /* @__PURE__ */ import_react5.default.createElement(
1887
1922
  import_TextField2.default,
1888
1923
  {
1889
1924
  label: "Alias",
@@ -1899,7 +1934,7 @@ var init_KeyFormDialog = __esm({
1899
1934
  required: true,
1900
1935
  fullWidth: true
1901
1936
  }
1902
- ), !isCreate ? null : /* @__PURE__ */ import_react4.default.createElement(
1937
+ ), !isCreate ? null : /* @__PURE__ */ import_react5.default.createElement(
1903
1938
  import_TextField2.default,
1904
1939
  {
1905
1940
  select: true,
@@ -1908,12 +1943,12 @@ var init_KeyFormDialog = __esm({
1908
1943
  onChange: (e) => setFormData({ duration: e.target.value }),
1909
1944
  fullWidth: true
1910
1945
  },
1911
- /* @__PURE__ */ import_react4.default.createElement(import_MenuItem.default, { value: "1d" }, "1 Day"),
1912
- /* @__PURE__ */ import_react4.default.createElement(import_MenuItem.default, { value: "7d" }, "7 Days"),
1913
- /* @__PURE__ */ import_react4.default.createElement(import_MenuItem.default, { value: "30d" }, "30 Days"),
1914
- /* @__PURE__ */ import_react4.default.createElement(import_MenuItem.default, { value: "90d" }, "90 Days"),
1915
- /* @__PURE__ */ import_react4.default.createElement(import_MenuItem.default, { value: "1y" }, "1 Year")
1916
- ), renderTeamField(), availableModels.length > 0 && /* @__PURE__ */ import_react4.default.createElement(
1946
+ /* @__PURE__ */ import_react5.default.createElement(import_MenuItem.default, { value: "1d" }, "1 Day"),
1947
+ /* @__PURE__ */ import_react5.default.createElement(import_MenuItem.default, { value: "7d" }, "7 Days"),
1948
+ /* @__PURE__ */ import_react5.default.createElement(import_MenuItem.default, { value: "30d" }, "30 Days"),
1949
+ /* @__PURE__ */ import_react5.default.createElement(import_MenuItem.default, { value: "90d" }, "90 Days"),
1950
+ /* @__PURE__ */ import_react5.default.createElement(import_MenuItem.default, { value: "1y" }, "1 Year")
1951
+ ), renderTeamField(), availableModels.length > 0 && /* @__PURE__ */ import_react5.default.createElement(
1917
1952
  import_Autocomplete.default,
1918
1953
  {
1919
1954
  multiple: true,
@@ -1922,8 +1957,8 @@ var init_KeyFormDialog = __esm({
1922
1957
  getOptionLabel: (m) => m.model_name,
1923
1958
  value: selectedModels,
1924
1959
  onChange: (_e, selected) => setFormData({ models: selected.map((m) => m.model_name) }),
1925
- renderOption: (props, m) => /* @__PURE__ */ import_react4.default.createElement("li", { ...props }, modelOption(m)),
1926
- renderInput: (params) => /* @__PURE__ */ import_react4.default.createElement(
1960
+ renderOption: (props, m) => /* @__PURE__ */ import_react5.default.createElement("li", { ...props }, modelOption(m)),
1961
+ renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(
1927
1962
  import_TextField2.default,
1928
1963
  {
1929
1964
  ...params,
@@ -1933,10 +1968,10 @@ var init_KeyFormDialog = __esm({
1933
1968
  }
1934
1969
  )
1935
1970
  }
1936
- ), allowUnlimitedBudget && /* @__PURE__ */ import_react4.default.createElement(
1971
+ ), allowUnlimitedBudget && /* @__PURE__ */ import_react5.default.createElement(
1937
1972
  import_FormControlLabel.default,
1938
1973
  {
1939
- control: /* @__PURE__ */ import_react4.default.createElement(
1974
+ control: /* @__PURE__ */ import_react5.default.createElement(
1940
1975
  import_Checkbox.default,
1941
1976
  {
1942
1977
  checked: unlimitedBudget,
@@ -1952,7 +1987,7 @@ var init_KeyFormDialog = __esm({
1952
1987
  ),
1953
1988
  label: "Unlimited budget"
1954
1989
  }
1955
- ), /* @__PURE__ */ import_react4.default.createElement(
1990
+ ), /* @__PURE__ */ import_react5.default.createElement(
1956
1991
  import_TextField2.default,
1957
1992
  {
1958
1993
  label: "Max Budget (USD)",
@@ -1965,7 +2000,7 @@ var init_KeyFormDialog = __esm({
1965
2000
  required: true,
1966
2001
  fullWidth: true
1967
2002
  }
1968
- ), /* @__PURE__ */ import_react4.default.createElement(import_Accordion.default, { disableGutters: true, elevation: 0, sx: { border: "1px solid", borderColor: "divider", "&:before": { display: "none" } } }, /* @__PURE__ */ import_react4.default.createElement(import_AccordionSummary.default, { expandIcon: /* @__PURE__ */ import_react4.default.createElement(import_icons_material3.ExpandMore, null) }, /* @__PURE__ */ import_react4.default.createElement(import_Typography4.default, { variant: "body2", fontWeight: 600 }, "Advanced")), /* @__PURE__ */ import_react4.default.createElement(import_AccordionDetails.default, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, /* @__PURE__ */ import_react4.default.createElement(
2003
+ ), /* @__PURE__ */ import_react5.default.createElement(import_Accordion.default, { disableGutters: true, elevation: 0, sx: { border: "1px solid", borderColor: "divider", "&:before": { display: "none" } } }, /* @__PURE__ */ import_react5.default.createElement(import_AccordionSummary.default, { expandIcon: /* @__PURE__ */ import_react5.default.createElement(import_icons_material3.ExpandMore, null) }, /* @__PURE__ */ import_react5.default.createElement(import_Typography4.default, { variant: "body2", fontWeight: 600 }, "Advanced")), /* @__PURE__ */ import_react5.default.createElement(import_AccordionDetails.default, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, /* @__PURE__ */ import_react5.default.createElement(
1969
2004
  import_TextField2.default,
1970
2005
  {
1971
2006
  label: "TPM Limit",
@@ -1975,7 +2010,7 @@ var init_KeyFormDialog = __esm({
1975
2010
  helperText: "Max tokens per minute this key can consume across all models. Leave blank for no limit.",
1976
2011
  fullWidth: true
1977
2012
  }
1978
- ), /* @__PURE__ */ import_react4.default.createElement(
2013
+ ), /* @__PURE__ */ import_react5.default.createElement(
1979
2014
  import_TextField2.default,
1980
2015
  {
1981
2016
  label: "RPM Limit",
@@ -1985,7 +2020,7 @@ var init_KeyFormDialog = __esm({
1985
2020
  helperText: "Max requests per minute this key can make across all models. Leave blank for no limit.",
1986
2021
  fullWidth: true
1987
2022
  }
1988
- ))), renderDangerZone())), /* @__PURE__ */ import_react4.default.createElement(import_DialogActions2.default, null, newKeyValue ? /* @__PURE__ */ import_react4.default.createElement(import_Button3.default, { onClick: handleClose, variant: "contained", color: "success" }, "Done") : /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement(import_Button3.default, { onClick: handleClose }, "Cancel"), /* @__PURE__ */ import_react4.default.createElement(
2023
+ ))), renderDangerZone())), /* @__PURE__ */ import_react5.default.createElement(import_DialogActions2.default, null, newKeyValue ? /* @__PURE__ */ import_react5.default.createElement(import_Button3.default, { onClick: handleClose, variant: "contained", color: "success" }, "Done") : /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(import_Button3.default, { onClick: handleClose }, "Cancel"), /* @__PURE__ */ import_react5.default.createElement(
1989
2024
  import_Button3.default,
1990
2025
  {
1991
2026
  onClick: isCreate ? handleGenerate : handleUpdate,
@@ -1993,18 +2028,18 @@ var init_KeyFormDialog = __esm({
1993
2028
  color: "primary",
1994
2029
  disabled: !canSubmit
1995
2030
  },
1996
- submitting ? /* @__PURE__ */ import_react4.default.createElement(import_CircularProgress2.default, { size: 24 }) : submitLabel
2031
+ submitting ? /* @__PURE__ */ import_react5.default.createElement(import_CircularProgress2.default, { size: 24 }) : submitLabel
1997
2032
  ))));
1998
2033
  };
1999
2034
  }
2000
2035
  });
2001
2036
 
2002
2037
  // src/components/ManageTeamDialog.tsx
2003
- var import_react5, import_Dialog3, import_DialogTitle3, import_DialogContent3, import_DialogActions3, import_TextField3, import_Button4, import_Alert2, import_Checkbox2, import_FormControlLabel2, import_Autocomplete2, 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;
2038
+ var import_react6, import_Dialog3, import_DialogTitle3, import_DialogContent3, import_DialogActions3, import_TextField3, import_Button4, import_Alert2, import_Checkbox2, import_FormControlLabel2, import_Autocomplete2, 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;
2004
2039
  var init_ManageTeamDialog = __esm({
2005
2040
  "src/components/ManageTeamDialog.tsx"() {
2006
2041
  "use strict";
2007
- import_react5 = __toESM(require("react"));
2042
+ import_react6 = __toESM(require("react"));
2008
2043
  import_Dialog3 = __toESM(require("@mui/material/Dialog"));
2009
2044
  import_DialogTitle3 = __toESM(require("@mui/material/DialogTitle"));
2010
2045
  import_DialogContent3 = __toESM(require("@mui/material/DialogContent"));
@@ -2061,29 +2096,29 @@ var init_ManageTeamDialog = __esm({
2061
2096
  mcpServers,
2062
2097
  onSaveMcpServers
2063
2098
  }) => {
2064
- const [alias, setAlias] = (0, import_react5.useState)("");
2065
- const [models, setModels] = (0, import_react5.useState)([]);
2066
- const [maxBudget, setMaxBudget] = (0, import_react5.useState)("");
2067
- const [unlimited, setUnlimited] = (0, import_react5.useState)(false);
2068
- const [budgetDuration, setBudgetDuration] = (0, import_react5.useState)("");
2069
- const [submitting, setSubmitting] = (0, import_react5.useState)(false);
2070
- const [error, setError] = (0, import_react5.useState)(null);
2071
- const [memberQuery, setMemberQuery] = (0, import_react5.useState)("");
2072
- const [memberRef, setMemberRef] = (0, import_react5.useState)("");
2073
- const [memberBudget, setMemberBudget] = (0, import_react5.useState)("");
2074
- const [memberBusy, setMemberBusy] = (0, import_react5.useState)(false);
2075
- const [memberError, setMemberError] = (0, import_react5.useState)(null);
2076
- const [kbIds, setKbIds] = (0, import_react5.useState)([]);
2077
- const [kbBusy, setKbBusy] = (0, import_react5.useState)(false);
2078
- const [kbError, setKbError] = (0, import_react5.useState)(null);
2079
- const [mcpIds, setMcpIds] = (0, import_react5.useState)([]);
2080
- const [mcpBusy, setMcpBusy] = (0, import_react5.useState)(false);
2081
- const [mcpError, setMcpError] = (0, import_react5.useState)(null);
2099
+ const [alias, setAlias] = (0, import_react6.useState)("");
2100
+ const [models, setModels] = (0, import_react6.useState)([]);
2101
+ const [maxBudget, setMaxBudget] = (0, import_react6.useState)("");
2102
+ const [unlimited, setUnlimited] = (0, import_react6.useState)(false);
2103
+ const [budgetDuration, setBudgetDuration] = (0, import_react6.useState)("");
2104
+ const [submitting, setSubmitting] = (0, import_react6.useState)(false);
2105
+ const [error, setError] = (0, import_react6.useState)(null);
2106
+ const [memberQuery, setMemberQuery] = (0, import_react6.useState)("");
2107
+ const [memberRef, setMemberRef] = (0, import_react6.useState)("");
2108
+ const [memberBudget, setMemberBudget] = (0, import_react6.useState)("");
2109
+ const [memberBusy, setMemberBusy] = (0, import_react6.useState)(false);
2110
+ const [memberError, setMemberError] = (0, import_react6.useState)(null);
2111
+ const [kbIds, setKbIds] = (0, import_react6.useState)([]);
2112
+ const [kbBusy, setKbBusy] = (0, import_react6.useState)(false);
2113
+ const [kbError, setKbError] = (0, import_react6.useState)(null);
2114
+ const [mcpIds, setMcpIds] = (0, import_react6.useState)([]);
2115
+ const [mcpBusy, setMcpBusy] = (0, import_react6.useState)(false);
2116
+ const [mcpError, setMcpError] = (0, import_react6.useState)(null);
2082
2117
  const allowUnlimitedBudget = config?.teamManagement?.allowUnlimitedBudget ?? false;
2083
2118
  const maxBudgetCeiling = config?.teamManagement?.maxBudgetCeiling ?? FALLBACK_BUDGET_CEILING;
2084
2119
  const hideBudgetForManagers = config?.display?.hideTeamBudgetForManagers ?? false;
2085
2120
  const budgetWriteOnly = hideBudgetForManagers && mode === "edit";
2086
- const members = (0, import_react5.useMemo)(() => team?.members_with_roles ?? [], [team]);
2121
+ const members = (0, import_react6.useMemo)(() => team?.members_with_roles ?? [], [team]);
2087
2122
  const showMembers = mode === "edit" && !!canManageMembers;
2088
2123
  const catalogApi = (0, import_core_plugin_api2.useApi)(import_plugin_catalog_react.catalogApiRef);
2089
2124
  const { value: catalogUsers, loading: usersLoading } = (0, import_react_use.useAsync)(async () => {
@@ -2098,7 +2133,7 @@ var init_ManageTeamDialog = __esm({
2098
2133
  return [];
2099
2134
  }
2100
2135
  }, [open, showMembers, catalogApi]);
2101
- const userOptions = (0, import_react5.useMemo)(() => {
2136
+ const userOptions = (0, import_react6.useMemo)(() => {
2102
2137
  const existingEmails = new Set(
2103
2138
  members.map((m) => m.user_email?.toLowerCase()).filter((e) => !!e)
2104
2139
  );
@@ -2113,7 +2148,7 @@ var init_ManageTeamDialog = __esm({
2113
2148
  };
2114
2149
  }).filter((o) => !(o.email && existingEmails.has(o.email.toLowerCase()))).sort((a, b) => a.label.localeCompare(b.label));
2115
2150
  }, [catalogUsers, members]);
2116
- (0, import_react5.useEffect)(() => {
2151
+ (0, import_react6.useEffect)(() => {
2117
2152
  if (open) {
2118
2153
  if (mode === "edit" && team) {
2119
2154
  setAlias(team.team_alias ?? "");
@@ -2269,7 +2304,7 @@ var init_ManageTeamDialog = __esm({
2269
2304
  const showMcpServers = mode === "edit" && !!canManageMcpServers;
2270
2305
  const mcpOptions = (mcpServers ?? []).map((s) => s.id);
2271
2306
  const mcpLabel = (id) => (mcpServers ?? []).find((s) => s.id === id)?.name ?? id;
2272
- return /* @__PURE__ */ import_react5.default.createElement(import_Dialog3.default, { open, onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ import_react5.default.createElement(import_DialogTitle3.default, null, mode === "create" ? "Create Team" : "Edit Team"), /* @__PURE__ */ import_react5.default.createElement(import_DialogContent3.default, { sx: { pt: 2, display: "flex", flexDirection: "column", gap: 2 } }, error && /* @__PURE__ */ import_react5.default.createElement(import_Alert2.default, { severity: "error" }, error), /* @__PURE__ */ import_react5.default.createElement(
2307
+ return /* @__PURE__ */ import_react6.default.createElement(import_Dialog3.default, { open, onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ import_react6.default.createElement(import_DialogTitle3.default, null, mode === "create" ? "Create Team" : "Edit Team"), /* @__PURE__ */ import_react6.default.createElement(import_DialogContent3.default, { sx: { pt: 2, display: "flex", flexDirection: "column", gap: 2 } }, error && /* @__PURE__ */ import_react6.default.createElement(import_Alert2.default, { severity: "error" }, error), /* @__PURE__ */ import_react6.default.createElement(
2273
2308
  import_TextField3.default,
2274
2309
  {
2275
2310
  label: "Team Alias",
@@ -2278,7 +2313,7 @@ var init_ManageTeamDialog = __esm({
2278
2313
  disabled: submitting,
2279
2314
  fullWidth: true
2280
2315
  }
2281
- ), /* @__PURE__ */ import_react5.default.createElement(
2316
+ ), /* @__PURE__ */ import_react6.default.createElement(
2282
2317
  import_Autocomplete2.default,
2283
2318
  {
2284
2319
  multiple: true,
@@ -2286,7 +2321,7 @@ var init_ManageTeamDialog = __esm({
2286
2321
  value: models,
2287
2322
  onChange: (_, newValue) => setModels(newValue),
2288
2323
  disabled: submitting,
2289
- renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(
2324
+ renderInput: (params) => /* @__PURE__ */ import_react6.default.createElement(
2290
2325
  import_TextField3.default,
2291
2326
  {
2292
2327
  ...params,
@@ -2296,7 +2331,7 @@ var init_ManageTeamDialog = __esm({
2296
2331
  }
2297
2332
  )
2298
2333
  }
2299
- ), /* @__PURE__ */ import_react5.default.createElement(
2334
+ ), /* @__PURE__ */ import_react6.default.createElement(
2300
2335
  import_TextField3.default,
2301
2336
  {
2302
2337
  label: budgetWriteOnly ? "New Max Budget ($)" : "Max Budget ($)",
@@ -2308,13 +2343,13 @@ var init_ManageTeamDialog = __esm({
2308
2343
  helperText: budgetWriteOnly ? "Current budget is hidden \u2014 leave blank to keep it, or enter a new value" : `Maximum: $${maxBudgetCeiling}`,
2309
2344
  fullWidth: true
2310
2345
  }
2311
- ), allowUnlimitedBudget && /* @__PURE__ */ import_react5.default.createElement(
2346
+ ), allowUnlimitedBudget && /* @__PURE__ */ import_react6.default.createElement(
2312
2347
  import_FormControlLabel2.default,
2313
2348
  {
2314
- control: /* @__PURE__ */ import_react5.default.createElement(import_Checkbox2.default, { checked: unlimited, onChange: (e) => setUnlimited(e.target.checked), disabled: submitting }),
2349
+ control: /* @__PURE__ */ import_react6.default.createElement(import_Checkbox2.default, { checked: unlimited, onChange: (e) => setUnlimited(e.target.checked), disabled: submitting }),
2315
2350
  label: "Unlimited Budget"
2316
2351
  }
2317
- ), /* @__PURE__ */ import_react5.default.createElement(
2352
+ ), /* @__PURE__ */ import_react6.default.createElement(
2318
2353
  import_TextField3.default,
2319
2354
  {
2320
2355
  select: true,
@@ -2325,8 +2360,8 @@ var init_ManageTeamDialog = __esm({
2325
2360
  helperText: "Spend-reset period for the team budget",
2326
2361
  fullWidth: true
2327
2362
  },
2328
- durationOptions.map((o) => /* @__PURE__ */ import_react5.default.createElement(import_MenuItem2.default, { key: o.value, value: o.value }, o.label))
2329
- ), 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(
2363
+ durationOptions.map((o) => /* @__PURE__ */ import_react6.default.createElement(import_MenuItem2.default, { key: o.value, value: o.value }, o.label))
2364
+ ), showMembers && /* @__PURE__ */ import_react6.default.createElement(import_Box5.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Divider2.default, { sx: { my: 1 } }), /* @__PURE__ */ import_react6.default.createElement(import_Typography5.default, { variant: "subtitle2", sx: { mb: 1 } }, "Members"), memberError && /* @__PURE__ */ import_react6.default.createElement(import_Alert2.default, { severity: "error", sx: { mb: 1 }, onClose: () => setMemberError(null) }, memberError), members.length === 0 ? /* @__PURE__ */ import_react6.default.createElement(import_Typography5.default, { variant: "body2", color: "text.secondary", sx: { mb: 1 } }, "No members yet.") : /* @__PURE__ */ import_react6.default.createElement(import_TableContainer2.default, { component: import_Paper3.default, variant: "outlined", sx: { borderRadius: 1.5, mb: 1.5 } }, /* @__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, "User"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, "Role"), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right", sx: { width: 40 } }))), /* @__PURE__ */ import_react6.default.createElement(import_TableBody2.default, null, members.map((m) => /* @__PURE__ */ import_react6.default.createElement(import_TableRow2.default, { key: m.user_id }, /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, null, m.user_email ? /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(import_Typography5.default, { variant: "body2" }, m.user_email), /* @__PURE__ */ import_react6.default.createElement(
2330
2365
  import_Typography5.default,
2331
2366
  {
2332
2367
  variant: "caption",
@@ -2334,14 +2369,14 @@ var init_ManageTeamDialog = __esm({
2334
2369
  sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 }
2335
2370
  },
2336
2371
  m.user_id
2337
- )) : /* @__PURE__ */ import_react5.default.createElement(
2372
+ )) : /* @__PURE__ */ import_react6.default.createElement(
2338
2373
  import_Typography5.default,
2339
2374
  {
2340
2375
  variant: "body2",
2341
2376
  sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" }
2342
2377
  },
2343
2378
  m.user_id
2344
- )), /* @__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(
2379
+ )), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, /* @__PURE__ */ import_react6.default.createElement(StatusPill, { label: m.role, tone: m.role === "admin" ? "accent" : "neutral", dot: false })), /* @__PURE__ */ import_react6.default.createElement(import_TableCell2.default, { align: "right" }, /* @__PURE__ */ import_react6.default.createElement(
2345
2380
  import_IconButton3.default,
2346
2381
  {
2347
2382
  edge: "end",
@@ -2350,8 +2385,8 @@ var init_ManageTeamDialog = __esm({
2350
2385
  disabled: memberBusy,
2351
2386
  onClick: () => handleRemoveMember(m.user_id)
2352
2387
  },
2353
- /* @__PURE__ */ import_react5.default.createElement(import_icons_material4.Delete, { fontSize: "small" })
2354
- ))))))), /* @__PURE__ */ import_react5.default.createElement(import_Box5.default, { sx: { display: "flex", gap: 1, alignItems: "flex-start", flexWrap: "wrap" } }, /* @__PURE__ */ import_react5.default.createElement(
2388
+ /* @__PURE__ */ import_react6.default.createElement(import_icons_material4.Delete, { fontSize: "small" })
2389
+ ))))))), /* @__PURE__ */ import_react6.default.createElement(import_Box5.default, { sx: { display: "flex", gap: 1, alignItems: "flex-start", flexWrap: "wrap" } }, /* @__PURE__ */ import_react6.default.createElement(
2355
2390
  import_Autocomplete2.default,
2356
2391
  {
2357
2392
  freeSolo: true,
@@ -2375,7 +2410,7 @@ var init_ManageTeamDialog = __esm({
2375
2410
  isOptionEqualToValue: (o, v) => o.ref === (typeof v === "string" ? v : v.ref),
2376
2411
  disabled: memberBusy,
2377
2412
  sx: { flex: 1, minWidth: 260 },
2378
- renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(
2413
+ renderInput: (params) => /* @__PURE__ */ import_react6.default.createElement(
2379
2414
  import_TextField3.default,
2380
2415
  {
2381
2416
  ...params,
@@ -2385,12 +2420,12 @@ var init_ManageTeamDialog = __esm({
2385
2420
  helperText: "Pick a catalog user, or paste a user entity ref",
2386
2421
  InputProps: {
2387
2422
  ...params.InputProps,
2388
- 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)
2423
+ endAdornment: /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, usersLoading ? /* @__PURE__ */ import_react6.default.createElement(import_CircularProgress3.default, { color: "inherit", size: 14 }) : null, params.InputProps.endAdornment)
2389
2424
  }
2390
2425
  }
2391
2426
  )
2392
2427
  }
2393
- ), /* @__PURE__ */ import_react5.default.createElement(
2428
+ ), /* @__PURE__ */ import_react6.default.createElement(
2394
2429
  import_TextField3.default,
2395
2430
  {
2396
2431
  label: "Max budget in team ($)",
@@ -2401,7 +2436,7 @@ var init_ManageTeamDialog = __esm({
2401
2436
  size: "small",
2402
2437
  sx: { width: 160 }
2403
2438
  }
2404
- ), /* @__PURE__ */ import_react5.default.createElement(
2439
+ ), /* @__PURE__ */ import_react6.default.createElement(
2405
2440
  import_Button4.default,
2406
2441
  {
2407
2442
  onClick: handleAddMember,
@@ -2410,7 +2445,7 @@ var init_ManageTeamDialog = __esm({
2410
2445
  sx: { mt: 0.5 }
2411
2446
  },
2412
2447
  "Add"
2413
- ))), showKnowledgeBases && /* @__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 } }, "Knowledge Bases"), /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "body2", color: "text.secondary", sx: { mb: 1 } }, "Attaching a knowledge base exposes its documents to every key in this team."), kbError && /* @__PURE__ */ import_react5.default.createElement(import_Alert2.default, { severity: "error", sx: { mb: 1 }, onClose: () => setKbError(null) }, kbError), /* @__PURE__ */ import_react5.default.createElement(
2448
+ ))), showKnowledgeBases && /* @__PURE__ */ import_react6.default.createElement(import_Box5.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Divider2.default, { sx: { my: 1 } }), /* @__PURE__ */ import_react6.default.createElement(import_Typography5.default, { variant: "subtitle2", sx: { mb: 1 } }, "Knowledge Bases"), /* @__PURE__ */ import_react6.default.createElement(import_Typography5.default, { variant: "body2", color: "text.secondary", sx: { mb: 1 } }, "Attaching a knowledge base exposes its documents to every key in this team."), kbError && /* @__PURE__ */ import_react6.default.createElement(import_Alert2.default, { severity: "error", sx: { mb: 1 }, onClose: () => setKbError(null) }, kbError), /* @__PURE__ */ import_react6.default.createElement(
2414
2449
  import_Autocomplete2.default,
2415
2450
  {
2416
2451
  multiple: true,
@@ -2419,9 +2454,9 @@ var init_ManageTeamDialog = __esm({
2419
2454
  getOptionLabel: kbLabel,
2420
2455
  onChange: (_, v) => setKbIds(v),
2421
2456
  disabled: kbBusy,
2422
- renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(import_TextField3.default, { ...params, label: "Attached knowledge bases" })
2457
+ renderInput: (params) => /* @__PURE__ */ import_react6.default.createElement(import_TextField3.default, { ...params, label: "Attached knowledge bases" })
2423
2458
  }
2424
- ), /* @__PURE__ */ import_react5.default.createElement(import_Box5.default, { sx: { display: "flex", justifyContent: "flex-end", mt: 1 } }, /* @__PURE__ */ import_react5.default.createElement(
2459
+ ), /* @__PURE__ */ import_react6.default.createElement(import_Box5.default, { sx: { display: "flex", justifyContent: "flex-end", mt: 1 } }, /* @__PURE__ */ import_react6.default.createElement(
2425
2460
  import_Button4.default,
2426
2461
  {
2427
2462
  onClick: handleSaveKnowledgeBases,
@@ -2429,7 +2464,7 @@ var init_ManageTeamDialog = __esm({
2429
2464
  variant: "outlined"
2430
2465
  },
2431
2466
  kbBusy ? "Saving\u2026" : "Save knowledge bases"
2432
- ))), showMcpServers && /* @__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 } }, "MCP Servers"), /* @__PURE__ */ import_react5.default.createElement(import_Typography5.default, { variant: "body2", color: "text.secondary", sx: { mb: 1 } }, "Attaching an MCP server lets every key in this team invoke that server's tools through the model \u2014 including any side effects those tools have."), mcpError && /* @__PURE__ */ import_react5.default.createElement(import_Alert2.default, { severity: "error", sx: { mb: 1 }, onClose: () => setMcpError(null) }, mcpError), /* @__PURE__ */ import_react5.default.createElement(
2467
+ ))), showMcpServers && /* @__PURE__ */ import_react6.default.createElement(import_Box5.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Divider2.default, { sx: { my: 1 } }), /* @__PURE__ */ import_react6.default.createElement(import_Typography5.default, { variant: "subtitle2", sx: { mb: 1 } }, "MCP Servers"), /* @__PURE__ */ import_react6.default.createElement(import_Typography5.default, { variant: "body2", color: "text.secondary", sx: { mb: 1 } }, "Attaching an MCP server lets every key in this team invoke that server's tools through the model \u2014 including any side effects those tools have."), mcpError && /* @__PURE__ */ import_react6.default.createElement(import_Alert2.default, { severity: "error", sx: { mb: 1 }, onClose: () => setMcpError(null) }, mcpError), /* @__PURE__ */ import_react6.default.createElement(
2433
2468
  import_Autocomplete2.default,
2434
2469
  {
2435
2470
  multiple: true,
@@ -2438,9 +2473,9 @@ var init_ManageTeamDialog = __esm({
2438
2473
  getOptionLabel: mcpLabel,
2439
2474
  onChange: (_, v) => setMcpIds(v),
2440
2475
  disabled: mcpBusy,
2441
- renderInput: (params) => /* @__PURE__ */ import_react5.default.createElement(import_TextField3.default, { ...params, label: "Attached MCP servers" })
2476
+ renderInput: (params) => /* @__PURE__ */ import_react6.default.createElement(import_TextField3.default, { ...params, label: "Attached MCP servers" })
2442
2477
  }
2443
- ), /* @__PURE__ */ import_react5.default.createElement(import_Box5.default, { sx: { display: "flex", justifyContent: "flex-end", mt: 1 } }, /* @__PURE__ */ import_react5.default.createElement(
2478
+ ), /* @__PURE__ */ import_react6.default.createElement(import_Box5.default, { sx: { display: "flex", justifyContent: "flex-end", mt: 1 } }, /* @__PURE__ */ import_react6.default.createElement(
2444
2479
  import_Button4.default,
2445
2480
  {
2446
2481
  onClick: handleSaveMcpServers,
@@ -2448,7 +2483,7 @@ var init_ManageTeamDialog = __esm({
2448
2483
  variant: "outlined"
2449
2484
  },
2450
2485
  mcpBusy ? "Saving\u2026" : "Save MCP servers"
2451
- )))), /* @__PURE__ */ import_react5.default.createElement(import_DialogActions3.default, null, /* @__PURE__ */ import_react5.default.createElement(import_Button4.default, { onClick: onClose, disabled: submitting }, "Cancel"), /* @__PURE__ */ import_react5.default.createElement(import_Button4.default, { onClick: handleSubmit, disabled: submitting, variant: "contained" }, submitting ? "Saving..." : "Save")));
2486
+ )))), /* @__PURE__ */ import_react6.default.createElement(import_DialogActions3.default, null, /* @__PURE__ */ import_react6.default.createElement(import_Button4.default, { onClick: onClose, disabled: submitting }, "Cancel"), /* @__PURE__ */ import_react6.default.createElement(import_Button4.default, { onClick: handleSubmit, disabled: submitting, variant: "contained" }, submitting ? "Saving..." : "Save")));
2452
2487
  };
2453
2488
  }
2454
2489
  });
@@ -2459,11 +2494,11 @@ function rateTone(rate) {
2459
2494
  if (rate >= 0.9) return "warning";
2460
2495
  return "danger";
2461
2496
  }
2462
- 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;
2497
+ var import_react7, 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;
2463
2498
  var init_UsageStats = __esm({
2464
2499
  "src/components/UsageStats.tsx"() {
2465
2500
  "use strict";
2466
- import_react6 = __toESM(require("react"));
2501
+ import_react7 = __toESM(require("react"));
2467
2502
  import_Paper4 = __toESM(require("@mui/material/Paper"));
2468
2503
  import_Box6 = __toESM(require("@mui/material/Box"));
2469
2504
  import_Typography6 = __toESM(require("@mui/material/Typography"));
@@ -2489,16 +2524,16 @@ var init_UsageStats = __esm({
2489
2524
  "30d": "Last 30 days"
2490
2525
  };
2491
2526
  fmtPct = (n) => `${(n * 100).toFixed(1)}%`;
2492
- ChartSkeleton = ({ height = 240 }) => /* @__PURE__ */ import_react6.default.createElement(import_Skeleton3.default, { variant: "rounded", height });
2527
+ ChartSkeleton = ({ height = 240 }) => /* @__PURE__ */ import_react7.default.createElement(import_Skeleton3.default, { variant: "rounded", height });
2493
2528
  ChartOrFallback = ({ loading, empty, height = 240, children }) => {
2494
- if (loading) return /* @__PURE__ */ import_react6.default.createElement(ChartSkeleton, { height });
2495
- if (empty) return /* @__PURE__ */ import_react6.default.createElement(EmptyState, { message: "No data for this period", height });
2496
- return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, children);
2529
+ if (loading) return /* @__PURE__ */ import_react7.default.createElement(ChartSkeleton, { height });
2530
+ if (empty) return /* @__PURE__ */ import_react7.default.createElement(EmptyState, { message: "No data for this period", height });
2531
+ return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, children);
2497
2532
  };
2498
2533
  SuccessRateCell = ({ rate, requests }) => {
2499
- if (requests === 0) return /* @__PURE__ */ import_react6.default.createElement(import_Typography6.default, { variant: "body2", color: "text.secondary" }, "\u2014");
2534
+ if (requests === 0) return /* @__PURE__ */ import_react7.default.createElement(import_Typography6.default, { variant: "body2", color: "text.secondary" }, "\u2014");
2500
2535
  const tone = rateTone(rate);
2501
- return /* @__PURE__ */ import_react6.default.createElement(import_Box6.default, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ import_react6.default.createElement(import_Box6.default, { width: 72, flexShrink: 0 }, /* @__PURE__ */ import_react6.default.createElement(Meter, { value: rate * 100, tone, height: 4 })), /* @__PURE__ */ import_react6.default.createElement(
2536
+ return /* @__PURE__ */ import_react7.default.createElement(import_Box6.default, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ import_react7.default.createElement(import_Box6.default, { width: 72, flexShrink: 0 }, /* @__PURE__ */ import_react7.default.createElement(Meter, { value: rate * 100, tone, height: 4 })), /* @__PURE__ */ import_react7.default.createElement(
2502
2537
  import_Typography6.default,
2503
2538
  {
2504
2539
  variant: "caption",
@@ -2517,8 +2552,8 @@ var init_UsageStats = __esm({
2517
2552
  userInfo
2518
2553
  }) => {
2519
2554
  const chart = useChartTheme();
2520
- const [selectedModel, setSelectedModel] = (0, import_react6.useState)("all");
2521
- const [tab, setTab] = (0, import_react6.useState)("costs");
2555
+ const [selectedModel, setSelectedModel] = (0, import_react7.useState)("all");
2556
+ const [tab, setTab] = (0, import_react7.useState)("costs");
2522
2557
  const handlePresetChange = (preset) => {
2523
2558
  const end = /* @__PURE__ */ new Date();
2524
2559
  const start = /* @__PURE__ */ new Date();
@@ -2532,7 +2567,7 @@ var init_UsageStats = __esm({
2532
2567
  }
2533
2568
  onDateRangeChange({ start, end }, preset);
2534
2569
  };
2535
- const dailyData = (0, import_react6.useMemo)(
2570
+ const dailyData = (0, import_react7.useMemo)(
2536
2571
  () => (usage?.daily_usage ?? []).map((d) => ({
2537
2572
  date: d.date,
2538
2573
  spend: d.spend,
@@ -2545,21 +2580,21 @@ var init_UsageStats = __esm({
2545
2580
  })),
2546
2581
  [usage]
2547
2582
  );
2548
- const cumulativeData = (0, import_react6.useMemo)(() => {
2583
+ const cumulativeData = (0, import_react7.useMemo)(() => {
2549
2584
  let cum = 0;
2550
2585
  return dailyData.map((d) => {
2551
2586
  cum += d.spend;
2552
2587
  return { date: d.date, cumulative: cum };
2553
2588
  });
2554
2589
  }, [dailyData]);
2555
- const successRateData = (0, import_react6.useMemo)(
2590
+ const successRateData = (0, import_react7.useMemo)(
2556
2591
  () => dailyData.filter((d) => d.apiRequests > 0).map((d) => ({
2557
2592
  date: d.date,
2558
2593
  successRate: parseFloat((d.successfulRequests / d.apiRequests * 100).toFixed(1))
2559
2594
  })),
2560
2595
  [dailyData]
2561
2596
  );
2562
- const { modelSpendByDate, topModels: topSpendModels } = (0, import_react6.useMemo)(() => {
2597
+ const { modelSpendByDate, topModels: topSpendModels } = (0, import_react7.useMemo)(() => {
2563
2598
  const rows = usage?.daily_by_model ?? [];
2564
2599
  const modelTotals = {};
2565
2600
  for (const r of rows) modelTotals[r.model] = (modelTotals[r.model] ?? 0) + r.spend;
@@ -2574,7 +2609,7 @@ var init_UsageStats = __esm({
2574
2609
  const hasOther = sorted.some((r) => r.Other > 0);
2575
2610
  return { modelSpendByDate: sorted, topModels: hasOther ? [...top, "Other"] : top };
2576
2611
  }, [usage]);
2577
- const modelRows = (0, import_react6.useMemo)(() => {
2612
+ const modelRows = (0, import_react7.useMemo)(() => {
2578
2613
  const entries = Object.entries(usage?.usage_by_model ?? {}).map(([model, d]) => ({
2579
2614
  model,
2580
2615
  spend: d.total_spend,
@@ -2588,11 +2623,11 @@ var init_UsageStats = __esm({
2588
2623
  }));
2589
2624
  return selectedModel === "all" ? entries : entries.filter((e) => e.model === selectedModel);
2590
2625
  }, [usage, selectedModel]);
2591
- const topModelSpendBars = (0, import_react6.useMemo)(
2626
+ const topModelSpendBars = (0, import_react7.useMemo)(
2592
2627
  () => [...modelRows].sort((a, b) => b.spend - a.spend).slice(0, 10),
2593
2628
  [modelRows]
2594
2629
  );
2595
- const keyRows = (0, import_react6.useMemo)(
2630
+ const keyRows = (0, import_react7.useMemo)(
2596
2631
  () => Object.entries(usage?.usage_by_key ?? {}).map(([keyHash, d]) => ({
2597
2632
  keyHash,
2598
2633
  keyAlias: d.key_alias ?? keyHash.slice(0, 8),
@@ -2609,7 +2644,7 @@ var init_UsageStats = __esm({
2609
2644
  })),
2610
2645
  [usage]
2611
2646
  );
2612
- const topKeySpendBars = (0, import_react6.useMemo)(
2647
+ const topKeySpendBars = (0, import_react7.useMemo)(
2613
2648
  () => [...keyRows].sort((a, b) => b.spend - a.spend).slice(0, 10),
2614
2649
  [keyRows]
2615
2650
  );
@@ -2647,23 +2682,23 @@ var init_UsageStats = __esm({
2647
2682
  ];
2648
2683
  const renderKeyRows = () => {
2649
2684
  if (loading) {
2650
- 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 })));
2685
+ return /* @__PURE__ */ import_react7.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { colSpan: 7, sx: { py: 3 } }, /* @__PURE__ */ import_react7.default.createElement(import_Skeleton3.default, { variant: "rounded", height: 80 })));
2651
2686
  }
2652
2687
  if (keyRows.length === 0) {
2653
- 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" })));
2688
+ return /* @__PURE__ */ import_react7.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { colSpan: 7 }, /* @__PURE__ */ import_react7.default.createElement(EmptyState, { message: "No key activity in this period" })));
2654
2689
  }
2655
- 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 }))));
2690
+ return [...keyRows].sort((a, b) => b.spend - a.spend || b.apiRequests - a.apiRequests).map((r) => /* @__PURE__ */ import_react7.default.createElement(import_TableRow3.default, { key: r.keyHash }, /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_Typography6.default, { variant: "body2", sx: { fontWeight: 600 } }, r.keyAlias), r.teamId ? /* @__PURE__ */ import_react7.default.createElement(import_Typography6.default, { variant: "caption", color: "text.secondary" }, "team: ", r.teamId) : null), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_Box6.default, { display: "flex", gap: 0.5, flexWrap: "wrap" }, r.models.slice(0, 3).map((m) => /* @__PURE__ */ import_react7.default.createElement(TagChip, { key: m, label: m, title: m })), r.models.length > 3 && /* @__PURE__ */ import_react7.default.createElement(TagChip, { label: `+${r.models.length - 3}`, mono: false }))), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtUsd(r.spend)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.apiRequests)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtCompact(r.totalTokens)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.failedRequests)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react7.default.createElement(SuccessRateCell, { rate: r.successRate, requests: r.apiRequests }))));
2656
2691
  };
2657
2692
  const renderModelRows = () => {
2658
2693
  if (loading) {
2659
- 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 })));
2694
+ return /* @__PURE__ */ import_react7.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { colSpan: 8, sx: { py: 3 } }, /* @__PURE__ */ import_react7.default.createElement(import_Skeleton3.default, { variant: "rounded", height: 80 })));
2660
2695
  }
2661
2696
  if (modelRows.length === 0) {
2662
- 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" })));
2697
+ return /* @__PURE__ */ import_react7.default.createElement(import_TableRow3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { colSpan: 8 }, /* @__PURE__ */ import_react7.default.createElement(EmptyState, { message: "No model activity in this period" })));
2663
2698
  }
2664
- 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 }))));
2699
+ return [...modelRows].sort((a, b) => b.spend - a.spend || b.totalTokens - a.totalTokens).map((r) => /* @__PURE__ */ import_react7.default.createElement(import_TableRow3.default, { key: r.model }, /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react7.default.createElement(import_Box6.default, { display: "flex", alignItems: "center", gap: 1 }, /* @__PURE__ */ import_react7.default.createElement(import_Box6.default, { sx: { width: 8, height: 8, borderRadius: "50%", bgcolor: chartColor(r.model), flexShrink: 0 } }), /* @__PURE__ */ import_react7.default.createElement(import_Typography6.default, { variant: "body2", sx: { fontWeight: 600 } }, r.model))), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtUsd(r.spend)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.apiRequests)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.successfulRequests)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtInt(r.failedRequests)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtCompact(r.promptTokens)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, fmtCompact(r.completionTokens)), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, null, /* @__PURE__ */ import_react7.default.createElement(SuccessRateCell, { rate: r.successRate, requests: r.apiRequests }))));
2665
2700
  };
2666
- const periodSelect = /* @__PURE__ */ import_react6.default.createElement(
2701
+ const periodSelect = /* @__PURE__ */ import_react7.default.createElement(
2667
2702
  import_TextField4.default,
2668
2703
  {
2669
2704
  select: true,
@@ -2673,17 +2708,17 @@ var init_UsageStats = __esm({
2673
2708
  onChange: (e) => handlePresetChange(e.target.value),
2674
2709
  sx: { minWidth: 160 }
2675
2710
  },
2676
- Object.keys(PRESET_LABELS).map((p) => /* @__PURE__ */ import_react6.default.createElement(import_MenuItem3.default, { key: p, value: p }, PRESET_LABELS[p]))
2711
+ Object.keys(PRESET_LABELS).map((p) => /* @__PURE__ */ import_react7.default.createElement(import_MenuItem3.default, { key: p, value: p }, PRESET_LABELS[p]))
2677
2712
  );
2678
- return /* @__PURE__ */ import_react6.default.createElement(
2713
+ return /* @__PURE__ */ import_react7.default.createElement(
2679
2714
  SectionCard,
2680
2715
  {
2681
2716
  title: "Usage Analytics",
2682
2717
  subtitle: `${PRESET_LABELS[currentPreset]} \xB7 ${dateRange.start.toLocaleDateString()} \u2013 ${dateRange.end.toLocaleDateString()}`,
2683
2718
  actions: periodSelect
2684
2719
  },
2685
- /* @__PURE__ */ import_react6.default.createElement(MetricStrip, { metrics }),
2686
- /* @__PURE__ */ import_react6.default.createElement(
2720
+ /* @__PURE__ */ import_react7.default.createElement(MetricStrip, { metrics }),
2721
+ /* @__PURE__ */ import_react7.default.createElement(
2687
2722
  import_Box6.default,
2688
2723
  {
2689
2724
  sx: {
@@ -2696,7 +2731,7 @@ var init_UsageStats = __esm({
2696
2731
  mb: 2
2697
2732
  }
2698
2733
  },
2699
- /* @__PURE__ */ import_react6.default.createElement(
2734
+ /* @__PURE__ */ import_react7.default.createElement(
2700
2735
  SegmentedControl,
2701
2736
  {
2702
2737
  value: tab,
@@ -2708,7 +2743,7 @@ var init_UsageStats = __esm({
2708
2743
  ]
2709
2744
  }
2710
2745
  ),
2711
- tab === "models" && /* @__PURE__ */ import_react6.default.createElement(
2746
+ tab === "models" && /* @__PURE__ */ import_react7.default.createElement(
2712
2747
  import_TextField4.default,
2713
2748
  {
2714
2749
  select: true,
@@ -2718,17 +2753,17 @@ var init_UsageStats = __esm({
2718
2753
  onChange: (e) => setSelectedModel(e.target.value),
2719
2754
  sx: { minWidth: 220 }
2720
2755
  },
2721
- /* @__PURE__ */ import_react6.default.createElement(import_MenuItem3.default, { value: "all" }, "All models"),
2722
- models.map((m) => /* @__PURE__ */ import_react6.default.createElement(import_MenuItem3.default, { key: m.model_name, value: m.model_name }, m.model_name))
2756
+ /* @__PURE__ */ import_react7.default.createElement(import_MenuItem3.default, { value: "all" }, "All models"),
2757
+ models.map((m) => /* @__PURE__ */ import_react7.default.createElement(import_MenuItem3.default, { key: m.model_name, value: m.model_name }, m.model_name))
2723
2758
  )
2724
2759
  ),
2725
- tab === "costs" && /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { container: true, spacing: 2 }, /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react6.default.createElement(ChartCard, { title: "Daily spend by model", height: 260 }, /* @__PURE__ */ import_react6.default.createElement(ChartOrFallback, { loading, empty: modelSpendByDate.length === 0, height: 260 }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.AreaChart, { data: modelSpendByDate, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { tickFormatter: fmtUsdCompact, width: 56, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(
2760
+ tab === "costs" && /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { container: true, spacing: 2 }, /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react7.default.createElement(ChartCard, { title: "Daily spend by model", height: 260 }, /* @__PURE__ */ import_react7.default.createElement(ChartOrFallback, { loading, empty: modelSpendByDate.length === 0, height: 260 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.AreaChart, { data: modelSpendByDate, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.YAxis, { tickFormatter: fmtUsdCompact, width: 56, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(
2726
2761
  import_recharts.Tooltip,
2727
2762
  {
2728
2763
  cursor: chart.cursor,
2729
- content: /* @__PURE__ */ import_react6.default.createElement(ChartTooltip, { valueFormatter: fmtUsd, hideZero: true })
2764
+ content: /* @__PURE__ */ import_react7.default.createElement(ChartTooltip, { valueFormatter: fmtUsd, hideZero: true })
2730
2765
  }
2731
- ), topSpendModels.map((m) => /* @__PURE__ */ import_react6.default.createElement(
2766
+ ), topSpendModels.map((m) => /* @__PURE__ */ import_react7.default.createElement(
2732
2767
  import_recharts.Area,
2733
2768
  {
2734
2769
  key: m,
@@ -2740,13 +2775,13 @@ var init_UsageStats = __esm({
2740
2775
  fill: chartColor(m),
2741
2776
  fillOpacity: 0.28
2742
2777
  }
2743
- ))))), !loading && topSpendModels.length > 0 && /* @__PURE__ */ import_react6.default.createElement(SeriesLegend, { series: topSpendModels.map((m) => ({ name: m, color: chartColor(m) })) }))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react6.default.createElement(ChartCard, { title: "Daily token usage" }, /* @__PURE__ */ import_react6.default.createElement(ChartOrFallback, { loading, empty: dailyData.length === 0 }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.AreaChart, { data: dailyData, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { tickFormatter: fmtCompact, width: 48, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react6.default.createElement(ChartTooltip, { valueFormatter: fmtInt }) }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Legend, { ...chart.legend }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Area, { type: "monotone", dataKey: "promptTokens", name: "Input", stackId: "tok", stroke: SERIES.input, strokeWidth: 1.5, fill: SERIES.input, fillOpacity: 0.25 }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Area, { type: "monotone", dataKey: "completionTokens", name: "Output", stackId: "tok", stroke: SERIES.output, strokeWidth: 1.5, fill: SERIES.output, fillOpacity: 0.25 })))))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react6.default.createElement(ChartCard, { title: "Daily requests" }, /* @__PURE__ */ import_react6.default.createElement(ChartOrFallback, { loading, empty: dailyData.length === 0 }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.BarChart, { data: dailyData, margin: { top: 4, right: 8, left: 0, bottom: 0 }, barCategoryGap: "30%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { tickFormatter: fmtCompact, width: 48, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react6.default.createElement(ChartTooltip, { valueFormatter: fmtInt }) }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Legend, { ...chart.legend }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Bar, { dataKey: "successfulRequests", name: "Successful", fill: SERIES.success, stackId: "r" }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Bar, { dataKey: "failedRequests", name: "Failed", fill: SERIES.failure, stackId: "r", radius: [3, 3, 0, 0] })))))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react6.default.createElement(ChartCard, { title: "Daily success rate" }, /* @__PURE__ */ import_react6.default.createElement(ChartOrFallback, { loading, empty: successRateData.length === 0 }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.LineChart, { data: successRateData, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { domain: [0, 100], tickFormatter: (v) => `${v}%`, width: 44, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(
2778
+ ))))), !loading && topSpendModels.length > 0 && /* @__PURE__ */ import_react7.default.createElement(SeriesLegend, { series: topSpendModels.map((m) => ({ name: m, color: chartColor(m) })) }))), /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react7.default.createElement(ChartCard, { title: "Daily token usage" }, /* @__PURE__ */ import_react7.default.createElement(ChartOrFallback, { loading, empty: dailyData.length === 0 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.AreaChart, { data: dailyData, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.YAxis, { tickFormatter: fmtCompact, width: 48, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react7.default.createElement(ChartTooltip, { valueFormatter: fmtInt }) }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Legend, { ...chart.legend }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Area, { type: "monotone", dataKey: "promptTokens", name: "Input", stackId: "tok", stroke: SERIES.input, strokeWidth: 1.5, fill: SERIES.input, fillOpacity: 0.25 }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Area, { type: "monotone", dataKey: "completionTokens", name: "Output", stackId: "tok", stroke: SERIES.output, strokeWidth: 1.5, fill: SERIES.output, fillOpacity: 0.25 })))))), /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react7.default.createElement(ChartCard, { title: "Daily requests" }, /* @__PURE__ */ import_react7.default.createElement(ChartOrFallback, { loading, empty: dailyData.length === 0 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.BarChart, { data: dailyData, margin: { top: 4, right: 8, left: 0, bottom: 0 }, barCategoryGap: "30%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.YAxis, { tickFormatter: fmtCompact, width: 48, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react7.default.createElement(ChartTooltip, { valueFormatter: fmtInt }) }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Legend, { ...chart.legend }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Bar, { dataKey: "successfulRequests", name: "Successful", fill: SERIES.success, stackId: "r" }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Bar, { dataKey: "failedRequests", name: "Failed", fill: SERIES.failure, stackId: "r", radius: [3, 3, 0, 0] })))))), /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react7.default.createElement(ChartCard, { title: "Daily success rate" }, /* @__PURE__ */ import_react7.default.createElement(ChartOrFallback, { loading, empty: successRateData.length === 0 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.LineChart, { data: successRateData, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.YAxis, { domain: [0, 100], tickFormatter: (v) => `${v}%`, width: 44, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(
2744
2779
  import_recharts.Tooltip,
2745
2780
  {
2746
2781
  cursor: chart.cursor,
2747
- content: /* @__PURE__ */ import_react6.default.createElement(ChartTooltip, { valueFormatter: (v) => `${v}%` })
2782
+ content: /* @__PURE__ */ import_react7.default.createElement(ChartTooltip, { valueFormatter: (v) => `${v}%` })
2748
2783
  }
2749
- ), /* @__PURE__ */ import_react6.default.createElement(import_recharts.ReferenceLine, { y: 100, stroke: SERIES.success, strokeDasharray: "4 4", strokeOpacity: 0.5 }), /* @__PURE__ */ import_react6.default.createElement(
2784
+ ), /* @__PURE__ */ import_react7.default.createElement(import_recharts.ReferenceLine, { y: 100, stroke: SERIES.success, strokeDasharray: "4 4", strokeOpacity: 0.5 }), /* @__PURE__ */ import_react7.default.createElement(
2750
2785
  import_recharts.Line,
2751
2786
  {
2752
2787
  type: "monotone",
@@ -2757,13 +2792,13 @@ var init_UsageStats = __esm({
2757
2792
  dot: { r: 2.5, strokeWidth: 0, fill: SERIES.input },
2758
2793
  activeDot: { r: 4 }
2759
2794
  }
2760
- )))))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react6.default.createElement(
2795
+ )))))), /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react7.default.createElement(
2761
2796
  ChartCard,
2762
2797
  {
2763
2798
  title: maxBudget > 0 ? "Cumulative spend vs budget" : "Cumulative spend",
2764
2799
  meta: maxBudget > 0 ? `${fmtUsd(totalCumSpend)} used \xB7 ${fmtUsd(Math.max(0, maxBudget - totalCumSpend))} left` : void 0
2765
2800
  },
2766
- /* @__PURE__ */ import_react6.default.createElement(ChartOrFallback, { loading, empty: cumulativeData.length === 0 }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.AreaChart, { data: cumulativeData, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react6.default.createElement(
2801
+ /* @__PURE__ */ import_react7.default.createElement(ChartOrFallback, { loading, empty: cumulativeData.length === 0 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.AreaChart, { data: cumulativeData, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(
2767
2802
  import_recharts.YAxis,
2768
2803
  {
2769
2804
  tickFormatter: fmtUsdCompact,
@@ -2771,13 +2806,13 @@ var init_UsageStats = __esm({
2771
2806
  domain: cumulativeDomain,
2772
2807
  ...chart.axis
2773
2808
  }
2774
- ), /* @__PURE__ */ import_react6.default.createElement(
2809
+ ), /* @__PURE__ */ import_react7.default.createElement(
2775
2810
  import_recharts.Tooltip,
2776
2811
  {
2777
2812
  cursor: chart.cursor,
2778
- content: /* @__PURE__ */ import_react6.default.createElement(ChartTooltip, { valueFormatter: fmtUsd })
2813
+ content: /* @__PURE__ */ import_react7.default.createElement(ChartTooltip, { valueFormatter: fmtUsd })
2779
2814
  }
2780
- ), maxBudget > 0 && /* @__PURE__ */ import_react6.default.createElement(
2815
+ ), maxBudget > 0 && /* @__PURE__ */ import_react7.default.createElement(
2781
2816
  import_recharts.ReferenceLine,
2782
2817
  {
2783
2818
  y: maxBudget,
@@ -2785,7 +2820,7 @@ var init_UsageStats = __esm({
2785
2820
  strokeDasharray: "5 4",
2786
2821
  label: { value: `Budget ${fmtUsd(maxBudget)}`, position: "insideTopRight", fontSize: 10, fill: SERIES.budget }
2787
2822
  }
2788
- ), /* @__PURE__ */ import_react6.default.createElement(
2823
+ ), /* @__PURE__ */ import_react7.default.createElement(
2789
2824
  import_recharts.Area,
2790
2825
  {
2791
2826
  type: "monotone",
@@ -2798,32 +2833,32 @@ var init_UsageStats = __esm({
2798
2833
  }
2799
2834
  ))))
2800
2835
  ))),
2801
- tab === "models" && /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { container: true, spacing: 2 }, /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react6.default.createElement(ChartCard, { title: "Spend by model", height: Math.max(200, topModelSpendBars.length * 34) }, /* @__PURE__ */ import_react6.default.createElement(
2836
+ tab === "models" && /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { container: true, spacing: 2 }, /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react7.default.createElement(ChartCard, { title: "Spend by model", height: Math.max(200, topModelSpendBars.length * 34) }, /* @__PURE__ */ import_react7.default.createElement(
2802
2837
  ChartOrFallback,
2803
2838
  {
2804
2839
  loading,
2805
2840
  empty: topModelSpendBars.length === 0,
2806
2841
  height: Math.max(200, topModelSpendBars.length * 34)
2807
2842
  },
2808
- /* @__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: fmtUsdCompact, ...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: fmtUsd, labelFormatter: (l) => l }) }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Bar, { dataKey: "spend", name: "Spend", radius: [0, 3, 3, 0], barSize: 14 }, topModelSpendBars.map((r) => /* @__PURE__ */ import_react6.default.createElement(import_recharts.Cell, { key: r.model, fill: chartColor(r.model) })))))
2809
- ))), /* @__PURE__ */ import_react6.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react6.default.createElement(ChartCard, { title: "Tokens by model", height: Math.max(200, topModelSpendBars.length * 34) }, /* @__PURE__ */ import_react6.default.createElement(
2843
+ /* @__PURE__ */ import_react7.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.BarChart, { data: topModelSpendBars, layout: "vertical", margin: { top: 0, right: 12, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.CartesianGrid, { ...chart.grid, vertical: true, horizontal: false }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.XAxis, { type: "number", tickFormatter: fmtUsdCompact, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.YAxis, { type: "category", dataKey: "model", width: 170, ...chart.axis, tick: { fontSize: 10.5, fill: chart.axis.tick.fill } }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react7.default.createElement(ChartTooltip, { valueFormatter: fmtUsd, labelFormatter: (l) => l }) }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Bar, { dataKey: "spend", name: "Spend", radius: [0, 3, 3, 0], barSize: 14 }, topModelSpendBars.map((r) => /* @__PURE__ */ import_react7.default.createElement(import_recharts.Cell, { key: r.model, fill: chartColor(r.model) })))))
2844
+ ))), /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12, md: 6 }, /* @__PURE__ */ import_react7.default.createElement(ChartCard, { title: "Tokens by model", height: Math.max(200, topModelSpendBars.length * 34) }, /* @__PURE__ */ import_react7.default.createElement(
2810
2845
  ChartOrFallback,
2811
2846
  {
2812
2847
  loading,
2813
2848
  empty: modelRows.length === 0,
2814
2849
  height: Math.max(200, topModelSpendBars.length * 34)
2815
2850
  },
2816
- /* @__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] })))
2817
- ))), /* @__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()))))),
2818
- 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(
2851
+ /* @__PURE__ */ import_react7.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.BarChart, { data: topModelSpendBars, layout: "vertical", margin: { top: 0, right: 12, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.CartesianGrid, { ...chart.grid, vertical: true, horizontal: false }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.XAxis, { type: "number", tickFormatter: fmtCompact, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.YAxis, { type: "category", dataKey: "model", width: 170, ...chart.axis, tick: { fontSize: 10.5, fill: chart.axis.tick.fill } }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react7.default.createElement(ChartTooltip, { valueFormatter: fmtInt, labelFormatter: (l) => l }) }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Legend, { ...chart.legend }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Bar, { dataKey: "promptTokens", name: "Input", fill: SERIES.input, stackId: "t", barSize: 14 }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Bar, { dataKey: "completionTokens", name: "Output", fill: SERIES.output, stackId: "t", barSize: 14, radius: [0, 3, 3, 0] })))
2852
+ ))), /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react7.default.createElement(import_TableContainer3.default, { component: import_Paper4.default, variant: "outlined", sx: { borderRadius: 2 } }, /* @__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, "Model"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Spend"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Requests"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Success"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Failed"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Input"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Output"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { sx: { width: 160 } }, "Success rate"))), /* @__PURE__ */ import_react7.default.createElement(import_TableBody3.default, null, renderModelRows()))))),
2853
+ tab === "keys" && /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { container: true, spacing: 2 }, (loading || topKeySpendBars.length > 0) && /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react7.default.createElement(ChartCard, { title: "Spend by key", height: Math.max(160, topKeySpendBars.length * 32) }, /* @__PURE__ */ import_react7.default.createElement(
2819
2854
  ChartOrFallback,
2820
2855
  {
2821
2856
  loading,
2822
2857
  empty: topKeySpendBars.length === 0,
2823
2858
  height: Math.max(160, topKeySpendBars.length * 32)
2824
2859
  },
2825
- /* @__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 })))
2826
- ))), /* @__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())))))
2860
+ /* @__PURE__ */ import_react7.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.BarChart, { data: topKeySpendBars, layout: "vertical", margin: { top: 0, right: 12, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts.CartesianGrid, { ...chart.grid, vertical: true, horizontal: false }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.XAxis, { type: "number", tickFormatter: fmtUsdCompact, ...chart.axis }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.YAxis, { type: "category", dataKey: "keyAlias", width: 160, ...chart.axis, tick: { fontSize: 10.5, fill: chart.axis.tick.fill } }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Tooltip, { cursor: chart.cursor, content: /* @__PURE__ */ import_react7.default.createElement(ChartTooltip, { valueFormatter: fmtUsd, labelFormatter: (l) => l }) }), /* @__PURE__ */ import_react7.default.createElement(import_recharts.Bar, { dataKey: "spend", name: "Spend", fill: SERIES.input, radius: [0, 3, 3, 0], barSize: 14 })))
2861
+ ))), /* @__PURE__ */ import_react7.default.createElement(import_Grid.default, { item: true, xs: 12 }, /* @__PURE__ */ import_react7.default.createElement(import_TableContainer3.default, { component: import_Paper4.default, variant: "outlined", sx: { borderRadius: 2 } }, /* @__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, "Key"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, null, "Models"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Spend"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Requests"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Tokens"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { align: "right" }, "Failed"), /* @__PURE__ */ import_react7.default.createElement(import_TableCell3.default, { sx: { width: 160 } }, "Success rate"))), /* @__PURE__ */ import_react7.default.createElement(import_TableBody3.default, null, renderKeyRows())))))
2827
2862
  );
2828
2863
  };
2829
2864
  }
@@ -2965,16 +3000,16 @@ function levelToneColor(tone, theme) {
2965
3000
  return theme.palette.primary.main;
2966
3001
  }
2967
3002
  }
2968
- var import_react7, import_Box7, import_Paper5, import_Typography7, import_styles4, import_core_components, LimitCard, TaggedLimit, MoreKeysNote, BudgetLimitList, LimitListPanel;
3003
+ var import_react8, import_Box7, import_Paper5, import_Typography7, import_styles4, import_core_components2, LimitCard, TaggedLimit, MoreKeysNote, BudgetLimitList, LimitListPanel;
2969
3004
  var init_BudgetLimitList = __esm({
2970
3005
  "src/components/BudgetLimitList.tsx"() {
2971
3006
  "use strict";
2972
- import_react7 = __toESM(require("react"));
3007
+ import_react8 = __toESM(require("react"));
2973
3008
  import_Box7 = __toESM(require("@mui/material/Box"));
2974
3009
  import_Paper5 = __toESM(require("@mui/material/Paper"));
2975
3010
  import_Typography7 = __toESM(require("@mui/material/Typography"));
2976
3011
  import_styles4 = require("@mui/material/styles");
2977
- import_core_components = require("@backstage/core-components");
3012
+ import_core_components2 = require("@backstage/core-components");
2978
3013
  init_budget();
2979
3014
  init_format();
2980
3015
  init_ui();
@@ -2982,7 +3017,7 @@ var init_BudgetLimitList = __esm({
2982
3017
  const tone = budgetTone2(limit.pct);
2983
3018
  const pct = Math.round(limit.pct);
2984
3019
  const closeTo = limit.softLimit !== void 0 && limit.spend >= limit.softLimit;
2985
- return /* @__PURE__ */ import_react7.default.createElement(import_Paper5.default, { variant: "outlined", sx: { px: 1.5, py: 1.25, borderRadius: 1.5 } }, /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { sx: { display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 1.5 } }, /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { sx: { minWidth: 0, flex: 1 } }, /* @__PURE__ */ import_react7.default.createElement(
3020
+ return /* @__PURE__ */ import_react8.default.createElement(import_Paper5.default, { variant: "outlined", sx: { px: 1.5, py: 1.25, borderRadius: 1.5 } }, /* @__PURE__ */ import_react8.default.createElement(import_Box7.default, { sx: { display: "flex", alignItems: "baseline", justifyContent: "space-between", gap: 1.5 } }, /* @__PURE__ */ import_react8.default.createElement(import_Box7.default, { sx: { minWidth: 0, flex: 1 } }, /* @__PURE__ */ import_react8.default.createElement(
2986
3021
  import_Typography7.default,
2987
3022
  {
2988
3023
  variant: "body2",
@@ -2990,7 +3025,7 @@ var init_BudgetLimitList = __esm({
2990
3025
  title: limit.sublabel ? `${limit.label} \xB7 ${limit.sublabel}` : limit.label
2991
3026
  },
2992
3027
  limit.label
2993
- ), limit.sublabel && /* @__PURE__ */ import_react7.default.createElement(
3028
+ ), limit.sublabel && /* @__PURE__ */ import_react8.default.createElement(
2994
3029
  import_Typography7.default,
2995
3030
  {
2996
3031
  variant: "caption",
@@ -3005,7 +3040,7 @@ var init_BudgetLimitList = __esm({
3005
3040
  }
3006
3041
  },
3007
3042
  limit.sublabel
3008
- )), limit.hidden ? /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "body2", sx: { fontWeight: 600, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" } }, pct, "% used") : /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "body2", sx: { fontWeight: 600, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" } }, fmtUsd(limit.spend), /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { component: "span", color: "text.secondary", sx: { fontWeight: 400 } }, " / ", fmtUsd(limit.budget)))), /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { sx: { mt: 1 } }, /* @__PURE__ */ import_react7.default.createElement(Meter, { value: limit.pct, tone, height: 6 })), /* @__PURE__ */ import_react7.default.createElement(
3043
+ )), limit.hidden ? /* @__PURE__ */ import_react8.default.createElement(import_Typography7.default, { variant: "body2", sx: { fontWeight: 600, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" } }, pct, "% used") : /* @__PURE__ */ import_react8.default.createElement(import_Typography7.default, { variant: "body2", sx: { fontWeight: 600, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" } }, fmtUsd(limit.spend), /* @__PURE__ */ import_react8.default.createElement(import_Box7.default, { component: "span", color: "text.secondary", sx: { fontWeight: 400 } }, " / ", fmtUsd(limit.budget)))), /* @__PURE__ */ import_react8.default.createElement(import_Box7.default, { sx: { mt: 1 } }, /* @__PURE__ */ import_react8.default.createElement(Meter, { value: limit.pct, tone, height: 6 })), /* @__PURE__ */ import_react8.default.createElement(
3009
3044
  import_Box7.default,
3010
3045
  {
3011
3046
  sx: {
@@ -3016,14 +3051,14 @@ var init_BudgetLimitList = __esm({
3016
3051
  mt: 0.75
3017
3052
  }
3018
3053
  },
3019
- /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, limit.hidden ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, "Hidden by admin") : /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, pct, "% of budget", closeTo && ` \xB7 soft-limit warning`)),
3020
- /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "caption", color: "text.secondary" }, fmtBudgetDuration(limit.budgetDuration) ? `resets ${fmtBudgetDuration(limit.budgetDuration)}` : "never resets")
3054
+ /* @__PURE__ */ import_react8.default.createElement(import_Typography7.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, limit.hidden ? /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, "Hidden by admin") : /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, pct, "% of budget", closeTo && ` \xB7 soft-limit warning`)),
3055
+ /* @__PURE__ */ import_react8.default.createElement(import_Typography7.default, { variant: "caption", color: "text.secondary" }, fmtBudgetDuration(limit.budgetDuration) ? `resets ${fmtBudgetDuration(limit.budgetDuration)}` : "never resets")
3021
3056
  ));
3022
3057
  };
3023
3058
  TaggedLimit = ({ limit }) => {
3024
3059
  const theme = (0, import_styles4.useTheme)();
3025
3060
  const tone = budgetTone2(limit.pct);
3026
- return /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, null, /* @__PURE__ */ import_react7.default.createElement(
3061
+ return /* @__PURE__ */ import_react8.default.createElement(import_Box7.default, null, /* @__PURE__ */ import_react8.default.createElement(
3027
3062
  import_Typography7.default,
3028
3063
  {
3029
3064
  sx: {
@@ -3036,7 +3071,7 @@ var init_BudgetLimitList = __esm({
3036
3071
  }
3037
3072
  },
3038
3073
  limit.kind
3039
- ), /* @__PURE__ */ import_react7.default.createElement(LimitCard, { limit }));
3074
+ ), /* @__PURE__ */ import_react8.default.createElement(LimitCard, { limit }));
3040
3075
  };
3041
3076
  MoreKeysNote = ({
3042
3077
  count,
@@ -3045,12 +3080,12 @@ var init_BudgetLimitList = __esm({
3045
3080
  }) => {
3046
3081
  const text = label ?? `+${count} more budgeted key${count > 1 ? "s" : ""} further from the cap`;
3047
3082
  if (!href) {
3048
- return /* @__PURE__ */ import_react7.default.createElement(import_Typography7.default, { variant: "caption", color: "text.secondary" }, text);
3083
+ return /* @__PURE__ */ import_react8.default.createElement(import_Typography7.default, { variant: "caption", color: "text.secondary" }, text);
3049
3084
  }
3050
- return /* @__PURE__ */ import_react7.default.createElement(import_core_components.Link, { to: href, variant: "caption" }, text, " \u2192");
3085
+ return /* @__PURE__ */ import_react8.default.createElement(import_core_components2.Link, { to: href, variant: "caption" }, text, " \u2192");
3051
3086
  };
3052
- BudgetLimitList = ({ limits, hiddenKeyCount = 0, keysHref }) => /* @__PURE__ */ import_react7.default.createElement(import_Box7.default, { sx: { display: "flex", flexDirection: "column", gap: 1.25 } }, limits.map((limit) => /* @__PURE__ */ import_react7.default.createElement(TaggedLimit, { key: `${limit.kind}:${limit.sublabel ?? limit.label}`, limit })), hiddenKeyCount > 0 && /* @__PURE__ */ import_react7.default.createElement(MoreKeysNote, { count: hiddenKeyCount, href: keysHref }));
3053
- LimitListPanel = ({ children }) => /* @__PURE__ */ import_react7.default.createElement(
3087
+ BudgetLimitList = ({ limits, hiddenKeyCount = 0, keysHref }) => /* @__PURE__ */ import_react8.default.createElement(import_Box7.default, { sx: { display: "flex", flexDirection: "column", gap: 1.25 } }, limits.map((limit) => /* @__PURE__ */ import_react8.default.createElement(TaggedLimit, { key: `${limit.kind}:${limit.sublabel ?? limit.label}`, limit })), hiddenKeyCount > 0 && /* @__PURE__ */ import_react8.default.createElement(MoreKeysNote, { count: hiddenKeyCount, href: keysHref }));
3088
+ LimitListPanel = ({ children }) => /* @__PURE__ */ import_react8.default.createElement(
3054
3089
  import_Box7.default,
3055
3090
  {
3056
3091
  sx: (theme) => ({
@@ -3066,11 +3101,11 @@ var init_BudgetLimitList = __esm({
3066
3101
  });
3067
3102
 
3068
3103
  // src/components/LiteLLMBudgetWidget.tsx
3069
- var import_react8, import_Paper6, import_Box8, import_Typography8, import_CircularProgress4, import_Alert3, import_Collapse, import_IconButton4, import_icons_material5, import_styles5, import_core_plugin_api3, LevelFrame, EmptyLimitCard, CLOSEST_LEVEL_LABEL, KEYS_PATH, HierarchyNote, FullBody, CompactBody, LiteLLMBudgetWidget;
3104
+ var import_react9, import_Paper6, import_Box8, import_Typography8, import_CircularProgress4, import_Alert3, import_Collapse, import_IconButton4, import_icons_material5, import_styles5, import_core_plugin_api3, LevelFrame, EmptyLimitCard, CLOSEST_LEVEL_LABEL, KEYS_PATH, HierarchyNote, FullBody, CompactBody, LiteLLMBudgetWidget;
3070
3105
  var init_LiteLLMBudgetWidget = __esm({
3071
3106
  "src/components/LiteLLMBudgetWidget.tsx"() {
3072
3107
  "use strict";
3073
- import_react8 = __toESM(require("react"));
3108
+ import_react9 = __toESM(require("react"));
3074
3109
  import_Paper6 = __toESM(require("@mui/material/Paper"));
3075
3110
  import_Box8 = __toESM(require("@mui/material/Box"));
3076
3111
  import_Typography8 = __toESM(require("@mui/material/Typography"));
@@ -3093,7 +3128,7 @@ var init_LiteLLMBudgetWidget = __esm({
3093
3128
  tone,
3094
3129
  isLast,
3095
3130
  children
3096
- }) => /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", gap: 1.5 } }, /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", flexDirection: "column", alignItems: "center", width: 26, flexShrink: 0 } }, /* @__PURE__ */ import_react8.default.createElement(
3131
+ }) => /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { display: "flex", gap: 1.5 } }, /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { display: "flex", flexDirection: "column", alignItems: "center", width: 26, flexShrink: 0 } }, /* @__PURE__ */ import_react9.default.createElement(
3097
3132
  import_Box8.default,
3098
3133
  {
3099
3134
  sx: (theme) => ({
@@ -3111,7 +3146,7 @@ var init_LiteLLMBudgetWidget = __esm({
3111
3146
  })
3112
3147
  },
3113
3148
  rank
3114
- ), /* @__PURE__ */ import_react8.default.createElement(
3149
+ ), /* @__PURE__ */ import_react9.default.createElement(
3115
3150
  import_Box8.default,
3116
3151
  {
3117
3152
  sx: (theme) => ({
@@ -3121,7 +3156,7 @@ var init_LiteLLMBudgetWidget = __esm({
3121
3156
  bgcolor: isLast ? "transparent" : (0, import_styles5.alpha)(theme.palette.text.primary, 0.12)
3122
3157
  })
3123
3158
  }
3124
- )), /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { flex: 1, minWidth: 0, pb: isLast ? 0 : 2 } }, /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", alignItems: "baseline", gap: 1, flexWrap: "wrap", mb: 0.75 } }, /* @__PURE__ */ import_react8.default.createElement(
3159
+ )), /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { flex: 1, minWidth: 0, pb: isLast ? 0 : 2 } }, /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { display: "flex", alignItems: "baseline", gap: 1, flexWrap: "wrap", mb: 0.75 } }, /* @__PURE__ */ import_react9.default.createElement(
3125
3160
  import_Typography8.default,
3126
3161
  {
3127
3162
  sx: (theme) => ({
@@ -3133,8 +3168,8 @@ var init_LiteLLMBudgetWidget = __esm({
3133
3168
  })
3134
3169
  },
3135
3170
  name
3136
- ), /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 11.5 } }, tagline), note && /* @__PURE__ */ import_react8.default.createElement(StatusPill, { label: note, tone: "neutral", dot: false, sx: { ml: "auto" } })), /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, children)));
3137
- EmptyLimitCard = ({ children }) => /* @__PURE__ */ import_react8.default.createElement(
3171
+ ), /* @__PURE__ */ import_react9.default.createElement(import_Typography8.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 11.5 } }, tagline), note && /* @__PURE__ */ import_react9.default.createElement(StatusPill, { label: note, tone: "neutral", dot: false, sx: { ml: "auto" } })), /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { display: "flex", flexDirection: "column", gap: 1 } }, children)));
3172
+ EmptyLimitCard = ({ children }) => /* @__PURE__ */ import_react9.default.createElement(
3138
3173
  import_Paper6.default,
3139
3174
  {
3140
3175
  variant: "outlined",
@@ -3145,7 +3180,7 @@ var init_LiteLLMBudgetWidget = __esm({
3145
3180
  bgcolor: (0, import_styles5.alpha)(theme.palette.text.primary, theme.palette.mode === "dark" ? 0.03 : 0.015)
3146
3181
  })
3147
3182
  },
3148
- /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", color: "text.secondary", sx: { fontSize: 13 } }, children)
3183
+ /* @__PURE__ */ import_react9.default.createElement(import_Typography8.default, { variant: "body2", color: "text.secondary", sx: { fontSize: 13 } }, children)
3149
3184
  );
3150
3185
  CLOSEST_LEVEL_LABEL = {
3151
3186
  key: "key",
@@ -3153,7 +3188,7 @@ var init_LiteLLMBudgetWidget = __esm({
3153
3188
  team: "team"
3154
3189
  };
3155
3190
  KEYS_PATH = "/litellm?tab=keys";
3156
- HierarchyNote = ({ withReset }) => /* @__PURE__ */ import_react8.default.createElement(
3191
+ HierarchyNote = ({ withReset }) => /* @__PURE__ */ import_react9.default.createElement(
3157
3192
  import_Box8.default,
3158
3193
  {
3159
3194
  sx: (theme) => ({
@@ -3164,11 +3199,11 @@ var init_LiteLLMBudgetWidget = __esm({
3164
3199
  borderColor: (0, import_styles5.alpha)(theme.palette.text.primary, 0.18)
3165
3200
  })
3166
3201
  },
3167
- /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "caption", color: "text.secondary", display: "block" }, /* @__PURE__ */ import_react8.default.createElement("b", null, "Order:"), " key \u2192 personal \u2192 team \u2192 global. The first cap you reach blocks the request; a key that belongs to a team uses the team's cap, not your personal one.", withReset && " A cap with a reset window drops to $0 when the window closes; without one it never resets.")
3202
+ /* @__PURE__ */ import_react9.default.createElement(import_Typography8.default, { variant: "caption", color: "text.secondary", display: "block" }, /* @__PURE__ */ import_react9.default.createElement("b", null, "Order:"), " key \u2192 personal \u2192 team \u2192 global. The first cap you reach blocks the request; a key that belongs to a team uses the team's cap, not your personal one.", withReset && " A cap with a reset window drops to $0 when the window closes; without one it never resets.")
3168
3203
  );
3169
3204
  FullBody = ({ summary }) => {
3170
3205
  const hasBudgetedKeys = summary.keys.length + summary.hiddenBudgetedKeys > 0;
3171
- return /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement(
3206
+ return /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(
3172
3207
  LevelFrame,
3173
3208
  {
3174
3209
  rank: 1,
@@ -3176,10 +3211,10 @@ var init_LiteLLMBudgetWidget = __esm({
3176
3211
  tagline: "per-key cap \xB7 highest priority",
3177
3212
  note: hasBudgetedKeys ? void 0 : "no key budgets set"
3178
3213
  },
3179
- !hasBudgetedKeys && /* @__PURE__ */ import_react8.default.createElement(EmptyLimitCard, null, "No key has a budget, so no key-level cap applies."),
3180
- summary.keys.map((k) => /* @__PURE__ */ import_react8.default.createElement(LimitCard, { key: k.sublabel ?? k.label, limit: k })),
3181
- summary.hiddenBudgetedKeys > 0 && /* @__PURE__ */ import_react8.default.createElement(MoreKeysNote, { count: summary.hiddenBudgetedKeys, href: KEYS_PATH })
3182
- ), /* @__PURE__ */ import_react8.default.createElement(
3214
+ !hasBudgetedKeys && /* @__PURE__ */ import_react9.default.createElement(EmptyLimitCard, null, "No key has a budget, so no key-level cap applies."),
3215
+ summary.keys.map((k) => /* @__PURE__ */ import_react9.default.createElement(LimitCard, { key: k.sublabel ?? k.label, limit: k })),
3216
+ summary.hiddenBudgetedKeys > 0 && /* @__PURE__ */ import_react9.default.createElement(MoreKeysNote, { count: summary.hiddenBudgetedKeys, href: KEYS_PATH })
3217
+ ), /* @__PURE__ */ import_react9.default.createElement(
3183
3218
  LevelFrame,
3184
3219
  {
3185
3220
  rank: 2,
@@ -3187,15 +3222,15 @@ var init_LiteLLMBudgetWidget = __esm({
3187
3222
  tagline: "cap on everything you spend with your own keys",
3188
3223
  note: "skipped for team-bound keys"
3189
3224
  },
3190
- summary.user ? /* @__PURE__ */ import_react8.default.createElement(LimitCard, { limit: summary.user }) : /* @__PURE__ */ import_react8.default.createElement(EmptyLimitCard, null, "No personal budget is set on your account.")
3191
- ), /* @__PURE__ */ import_react8.default.createElement(LevelFrame, { rank: 3, name: "Team", tagline: "shared cap for all keys in a team (if any)" }, summary.teams.length > 0 ? summary.teams.map((t) => /* @__PURE__ */ import_react8.default.createElement(LimitCard, { key: t.sublabel ?? t.label, limit: t })) : /* @__PURE__ */ import_react8.default.createElement(EmptyLimitCard, null, "No team you belong to has a budget.")), /* @__PURE__ */ import_react8.default.createElement(LevelFrame, { rank: 4, name: "Global", tagline: "proxy-wide cap set by your admin", isLast: true }, /* @__PURE__ */ import_react8.default.createElement(EmptyLimitCard, null, "Configured by your admin in the proxy config \u2014 it isn't visible from this page. When set, it limits spend across every request on the proxy.")), /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { mt: 2 } }, /* @__PURE__ */ import_react8.default.createElement(HierarchyNote, { withReset: true })));
3225
+ summary.user ? /* @__PURE__ */ import_react9.default.createElement(LimitCard, { limit: summary.user }) : /* @__PURE__ */ import_react9.default.createElement(EmptyLimitCard, null, "No personal budget is set on your account.")
3226
+ ), /* @__PURE__ */ import_react9.default.createElement(LevelFrame, { rank: 3, name: "Team", tagline: "shared cap for all keys in a team (if any)" }, summary.teams.length > 0 ? summary.teams.map((t) => /* @__PURE__ */ import_react9.default.createElement(LimitCard, { key: t.sublabel ?? t.label, limit: t })) : /* @__PURE__ */ import_react9.default.createElement(EmptyLimitCard, null, "No team you belong to has a budget.")), /* @__PURE__ */ import_react9.default.createElement(LevelFrame, { rank: 4, name: "Global", tagline: "proxy-wide cap set by your admin", isLast: true }, /* @__PURE__ */ import_react9.default.createElement(EmptyLimitCard, null, "Configured by your admin in the proxy config \u2014 it isn't visible from this page. When set, it limits spend across every request on the proxy.")), /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { mt: 2 } }, /* @__PURE__ */ import_react9.default.createElement(HierarchyNote, { withReset: true })));
3192
3227
  };
3193
3228
  CompactBody = ({ summary }) => {
3194
3229
  const { count } = budgetHeadline(summary);
3195
3230
  if (count === 0) {
3196
- return /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "body2", color: "text.secondary", sx: { fontSize: 13 } }, "No budget limits apply to you right now.");
3231
+ return /* @__PURE__ */ import_react9.default.createElement(import_Typography8.default, { variant: "body2", color: "text.secondary", sx: { fontSize: 13 } }, "No budget limits apply to you right now.");
3197
3232
  }
3198
- return /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", flexDirection: "column", gap: 1.25 } }, /* @__PURE__ */ import_react8.default.createElement(HierarchyNote, null), summary.keys.map((k) => /* @__PURE__ */ import_react8.default.createElement(TaggedLimit, { key: k.sublabel ?? k.label, limit: k })), summary.hiddenBudgetedKeys > 0 && /* @__PURE__ */ import_react8.default.createElement(MoreKeysNote, { count: summary.hiddenBudgetedKeys, href: KEYS_PATH }), summary.user && /* @__PURE__ */ import_react8.default.createElement(TaggedLimit, { limit: summary.user }), summary.teams.map((t) => /* @__PURE__ */ import_react8.default.createElement(TaggedLimit, { key: t.sublabel ?? t.label, limit: t })));
3233
+ return /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { display: "flex", flexDirection: "column", gap: 1.25 } }, /* @__PURE__ */ import_react9.default.createElement(HierarchyNote, null), summary.keys.map((k) => /* @__PURE__ */ import_react9.default.createElement(TaggedLimit, { key: k.sublabel ?? k.label, limit: k })), summary.hiddenBudgetedKeys > 0 && /* @__PURE__ */ import_react9.default.createElement(MoreKeysNote, { count: summary.hiddenBudgetedKeys, href: KEYS_PATH }), summary.user && /* @__PURE__ */ import_react9.default.createElement(TaggedLimit, { limit: summary.user }), summary.teams.map((t) => /* @__PURE__ */ import_react9.default.createElement(TaggedLimit, { key: t.sublabel ?? t.label, limit: t })));
3199
3234
  };
3200
3235
  LiteLLMBudgetWidget = ({
3201
3236
  title = "Budget Policy",
@@ -3206,13 +3241,13 @@ var init_LiteLLMBudgetWidget = __esm({
3206
3241
  action
3207
3242
  }) => {
3208
3243
  const api = (0, import_core_plugin_api3.useApi)(liteLlmApiRef);
3209
- const [loading, setLoading] = (0, import_react8.useState)(true);
3210
- const [error, setError] = (0, import_react8.useState)(null);
3211
- const [user, setUser] = (0, import_react8.useState)(null);
3212
- const [teams, setTeams] = (0, import_react8.useState)([]);
3213
- const [keys, setKeys] = (0, import_react8.useState)([]);
3214
- const [expanded, setExpanded] = (0, import_react8.useState)(defaultExpanded);
3215
- (0, import_react8.useEffect)(() => {
3244
+ const [loading, setLoading] = (0, import_react9.useState)(true);
3245
+ const [error, setError] = (0, import_react9.useState)(null);
3246
+ const [user, setUser] = (0, import_react9.useState)(null);
3247
+ const [teams, setTeams] = (0, import_react9.useState)([]);
3248
+ const [keys, setKeys] = (0, import_react9.useState)([]);
3249
+ const [expanded, setExpanded] = (0, import_react9.useState)(defaultExpanded);
3250
+ (0, import_react9.useEffect)(() => {
3216
3251
  let cancelled = false;
3217
3252
  setLoading(true);
3218
3253
  setError(null);
@@ -3236,18 +3271,18 @@ var init_LiteLLMBudgetWidget = __esm({
3236
3271
  cancelled = true;
3237
3272
  };
3238
3273
  }, [api]);
3239
- const summary = (0, import_react8.useMemo)(
3274
+ const summary = (0, import_react9.useMemo)(
3240
3275
  () => buildBudgetSummary(user, teams, keys, maxKeys),
3241
3276
  [user, teams, keys, maxKeys]
3242
3277
  );
3243
- const headline = (0, import_react8.useMemo)(() => budgetHeadline(summary), [summary]);
3278
+ const headline = (0, import_react9.useMemo)(() => budgetHeadline(summary), [summary]);
3244
3279
  const limitsWord = `${headline.count} limit${headline.count === 1 ? "" : "s"}`;
3245
3280
  const closestWord = headline.closest === null ? "" : ` \xB7 closest: ${CLOSEST_LEVEL_LABEL[headline.closest.kind]} ${Math.round(
3246
3281
  headline.closest.pct
3247
3282
  )}%`;
3248
3283
  const summaryText = headline.count === 0 ? "no limits apply" : `${limitsWord}${closestWord}`;
3249
- const body = /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, loading && /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 140 }, /* @__PURE__ */ import_react8.default.createElement(import_CircularProgress4.default, { size: 32 })), !loading && error && /* @__PURE__ */ import_react8.default.createElement(import_Alert3.default, { severity: "error", sx: { mt: 0.5 } }, error), !loading && !error && (compact ? /* @__PURE__ */ import_react8.default.createElement(CompactBody, { summary }) : /* @__PURE__ */ import_react8.default.createElement(FullBody, { summary })));
3250
- return /* @__PURE__ */ import_react8.default.createElement(import_Paper6.default, { sx: { p: 2 } }, collapsible ? /* @__PURE__ */ import_react8.default.createElement(
3284
+ const body = /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, loading && /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 140 }, /* @__PURE__ */ import_react9.default.createElement(import_CircularProgress4.default, { size: 32 })), !loading && error && /* @__PURE__ */ import_react9.default.createElement(import_Alert3.default, { severity: "error", sx: { mt: 0.5 } }, error), !loading && !error && (compact ? /* @__PURE__ */ import_react9.default.createElement(CompactBody, { summary }) : /* @__PURE__ */ import_react9.default.createElement(FullBody, { summary })));
3285
+ return /* @__PURE__ */ import_react9.default.createElement(import_Paper6.default, { sx: { p: 2 } }, collapsible ? /* @__PURE__ */ import_react9.default.createElement(
3251
3286
  import_Box8.default,
3252
3287
  {
3253
3288
  onClick: () => setExpanded((e) => !e),
@@ -3260,14 +3295,14 @@ var init_LiteLLMBudgetWidget = __esm({
3260
3295
  mb: expanded ? 1.5 : 0
3261
3296
  }
3262
3297
  },
3263
- /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { minWidth: 0, flex: 1 } }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "h6", lineHeight: 1.2 }, title), !loading && !error && /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { mt: 0.5 } }, /* @__PURE__ */ import_react8.default.createElement(
3298
+ /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { minWidth: 0, flex: 1 } }, /* @__PURE__ */ import_react9.default.createElement(import_Typography8.default, { variant: "h6", lineHeight: 1.2 }, title), !loading && !error && /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { mt: 0.5 } }, /* @__PURE__ */ import_react9.default.createElement(
3264
3299
  StatusPill,
3265
3300
  {
3266
3301
  label: summaryText,
3267
3302
  tone: budgetTone2(headline.closest?.pct ?? 0)
3268
3303
  }
3269
3304
  ))),
3270
- /* @__PURE__ */ import_react8.default.createElement(
3305
+ /* @__PURE__ */ import_react9.default.createElement(
3271
3306
  import_IconButton4.default,
3272
3307
  {
3273
3308
  size: "small",
@@ -3283,9 +3318,9 @@ var init_LiteLLMBudgetWidget = __esm({
3283
3318
  transition: theme.transitions.create("transform")
3284
3319
  })
3285
3320
  },
3286
- /* @__PURE__ */ import_react8.default.createElement(import_icons_material5.ExpandMore, null)
3321
+ /* @__PURE__ */ import_react9.default.createElement(import_icons_material5.ExpandMore, null)
3287
3322
  )
3288
- ) : /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { mb: 1.5 } }, /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "h6", lineHeight: 1.2 }, title), /* @__PURE__ */ import_react8.default.createElement(import_Typography8.default, { variant: "caption", color: "text.secondary" }, "How LiteLLM caps spend \u2014 and where you stand right now")), collapsible ? /* @__PURE__ */ import_react8.default.createElement(import_Collapse.default, { in: expanded, unmountOnExit: true }, body) : body, action && /* @__PURE__ */ import_react8.default.createElement(
3323
+ ) : /* @__PURE__ */ import_react9.default.createElement(import_Box8.default, { sx: { mb: 1.5 } }, /* @__PURE__ */ import_react9.default.createElement(import_Typography8.default, { variant: "h6", lineHeight: 1.2 }, title), /* @__PURE__ */ import_react9.default.createElement(import_Typography8.default, { variant: "caption", color: "text.secondary" }, "How LiteLLM caps spend \u2014 and where you stand right now")), collapsible ? /* @__PURE__ */ import_react9.default.createElement(import_Collapse.default, { in: expanded, unmountOnExit: true }, body) : body, action && /* @__PURE__ */ import_react9.default.createElement(
3289
3324
  import_Box8.default,
3290
3325
  {
3291
3326
  sx: (theme) => ({
@@ -3315,11 +3350,11 @@ function budgetStatValue(hidden, budget) {
3315
3350
  if (budget > 0) return fmtUsd2(budget);
3316
3351
  return "Unlimited";
3317
3352
  }
3318
- var import_react9, import_Paper7, import_Box9, import_Typography9, import_Skeleton4, import_Divider3, import_Table4, import_TableBody4, import_TableCell4, import_TableHead4, import_TableRow4, import_TableContainer4, import_Collapse2, import_IconButton5, import_Button5, import_CircularProgress5, import_styles6, import_icons_material6, import_recharts2, fmtUsd2, TeamCard, TeamUsage;
3353
+ var import_react10, import_Paper7, import_Box9, import_Typography9, import_Skeleton4, import_Divider3, import_Table4, import_TableBody4, import_TableCell4, import_TableHead4, import_TableRow4, import_TableContainer4, import_Collapse2, import_IconButton5, import_Button5, import_CircularProgress5, import_styles6, import_icons_material6, import_recharts2, fmtUsd2, TeamCard, TeamUsage;
3319
3354
  var init_TeamUsage = __esm({
3320
3355
  "src/components/TeamUsage.tsx"() {
3321
3356
  "use strict";
3322
- import_react9 = __toESM(require("react"));
3357
+ import_react10 = __toESM(require("react"));
3323
3358
  import_Paper7 = __toESM(require("@mui/material/Paper"));
3324
3359
  import_Box9 = __toESM(require("@mui/material/Box"));
3325
3360
  import_Typography9 = __toESM(require("@mui/material/Typography"));
@@ -3341,7 +3376,7 @@ var init_TeamUsage = __esm({
3341
3376
  init_ui();
3342
3377
  fmtUsd2 = (n) => `$${(n ?? 0).toFixed(2)}`;
3343
3378
  TeamCard = ({ team, usage, usageLoading, canManage, onEditTeam }) => {
3344
- const [expanded, setExpanded] = (0, import_react9.useState)(false);
3379
+ const [expanded, setExpanded] = (0, import_react10.useState)(false);
3345
3380
  const chart = useChartTheme();
3346
3381
  const hidden = team.budget_hidden === true;
3347
3382
  const budget = hidden ? 0 : team.max_budget ?? 0;
@@ -3353,10 +3388,10 @@ var init_TeamUsage = __esm({
3353
3388
  const renderDailySpendSection = () => {
3354
3389
  if (hidden) return null;
3355
3390
  if (usageLoading) {
3356
- return /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { display: "flex", justifyContent: "center", py: 3 }, /* @__PURE__ */ import_react9.default.createElement(import_CircularProgress5.default, { size: 22 }));
3391
+ return /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { display: "flex", justifyContent: "center", py: 3 }, /* @__PURE__ */ import_react10.default.createElement(import_CircularProgress5.default, { size: 22 }));
3357
3392
  }
3358
3393
  if (dailyData.length === 0) return null;
3359
- return /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { mb: 2.5 }, /* @__PURE__ */ import_react9.default.createElement(
3394
+ return /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { mb: 2.5 }, /* @__PURE__ */ import_react10.default.createElement(
3360
3395
  import_Typography9.default,
3361
3396
  {
3362
3397
  variant: "caption",
@@ -3364,13 +3399,13 @@ var init_TeamUsage = __esm({
3364
3399
  sx: { display: "block", fontSize: 11, fontWeight: 700, letterSpacing: "0.07em", textTransform: "uppercase", mb: 1 }
3365
3400
  },
3366
3401
  "Daily spend"
3367
- ), /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { height: 150 }, /* @__PURE__ */ import_react9.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react9.default.createElement(import_recharts2.AreaChart, { data: dailyData, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react9.default.createElement(import_recharts2.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react9.default.createElement(import_recharts2.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react9.default.createElement(import_recharts2.YAxis, { tickFormatter: fmtUsdCompact, width: 52, ...chart.axis }), /* @__PURE__ */ import_react9.default.createElement(
3402
+ ), /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { height: 150 }, /* @__PURE__ */ import_react10.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react10.default.createElement(import_recharts2.AreaChart, { data: dailyData, margin: { top: 4, right: 8, left: 0, bottom: 0 } }, /* @__PURE__ */ import_react10.default.createElement(import_recharts2.CartesianGrid, { ...chart.grid }), /* @__PURE__ */ import_react10.default.createElement(import_recharts2.XAxis, { dataKey: "date", tickFormatter: fmtDateShort, ...chart.axis }), /* @__PURE__ */ import_react10.default.createElement(import_recharts2.YAxis, { tickFormatter: fmtUsdCompact, width: 52, ...chart.axis }), /* @__PURE__ */ import_react10.default.createElement(
3368
3403
  import_recharts2.Tooltip,
3369
3404
  {
3370
3405
  cursor: chart.cursor,
3371
- content: /* @__PURE__ */ import_react9.default.createElement(ChartTooltip, { valueFormatter: (v) => `$${v.toFixed(4)}` })
3406
+ content: /* @__PURE__ */ import_react10.default.createElement(ChartTooltip, { valueFormatter: (v) => `$${v.toFixed(4)}` })
3372
3407
  }
3373
- ), /* @__PURE__ */ import_react9.default.createElement(
3408
+ ), /* @__PURE__ */ import_react10.default.createElement(
3374
3409
  import_recharts2.Area,
3375
3410
  {
3376
3411
  type: "monotone",
@@ -3383,7 +3418,7 @@ var init_TeamUsage = __esm({
3383
3418
  }
3384
3419
  )))));
3385
3420
  };
3386
- const sectionLabel = (label) => /* @__PURE__ */ import_react9.default.createElement(
3421
+ const sectionLabel = (label) => /* @__PURE__ */ import_react10.default.createElement(
3387
3422
  import_Typography9.default,
3388
3423
  {
3389
3424
  variant: "caption",
@@ -3392,7 +3427,7 @@ var init_TeamUsage = __esm({
3392
3427
  },
3393
3428
  label
3394
3429
  );
3395
- return /* @__PURE__ */ import_react9.default.createElement(import_Paper7.default, { variant: "outlined", sx: { borderRadius: 2, p: 2.5 } }, /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { display: "flex", alignItems: "center", gap: 1.5 }, /* @__PURE__ */ import_react9.default.createElement(
3430
+ return /* @__PURE__ */ import_react10.default.createElement(import_Paper7.default, { variant: "outlined", sx: { borderRadius: 2, p: 2.5 } }, /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { display: "flex", alignItems: "center", gap: 1.5 }, /* @__PURE__ */ import_react10.default.createElement(
3396
3431
  import_Box9.default,
3397
3432
  {
3398
3433
  sx: (theme) => ({
@@ -3407,8 +3442,8 @@ var init_TeamUsage = __esm({
3407
3442
  color: theme.palette.primary.main
3408
3443
  })
3409
3444
  },
3410
- /* @__PURE__ */ import_react9.default.createElement(import_icons_material6.Group, { fontSize: "small" })
3411
- ), /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { flexGrow: 1, minWidth: 0 }, /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "subtitle1", sx: { fontWeight: 600, lineHeight: 1.3 } }, team.team_alias || "Untitled team"), /* @__PURE__ */ import_react9.default.createElement(
3445
+ /* @__PURE__ */ import_react10.default.createElement(import_icons_material6.Group, { fontSize: "small" })
3446
+ ), /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { flexGrow: 1, minWidth: 0 }, /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "subtitle1", sx: { fontWeight: 600, lineHeight: 1.3 } }, team.team_alias || "Untitled team"), /* @__PURE__ */ import_react10.default.createElement(
3412
3447
  import_Typography9.default,
3413
3448
  {
3414
3449
  variant: "caption",
@@ -3416,7 +3451,7 @@ var init_TeamUsage = __esm({
3416
3451
  sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 }
3417
3452
  },
3418
3453
  team.team_id
3419
- )), isOver && /* @__PURE__ */ import_react9.default.createElement(StatusPill, { label: "Over budget", tone: "danger" }), isNear && /* @__PURE__ */ import_react9.default.createElement(StatusPill, { label: "Near limit", tone: "warning" }), canManage && onEditTeam && /* @__PURE__ */ import_react9.default.createElement(
3454
+ )), isOver && /* @__PURE__ */ import_react10.default.createElement(StatusPill, { label: "Over budget", tone: "danger" }), isNear && /* @__PURE__ */ import_react10.default.createElement(StatusPill, { label: "Near limit", tone: "warning" }), canManage && onEditTeam && /* @__PURE__ */ import_react10.default.createElement(
3420
3455
  import_Button5.default,
3421
3456
  {
3422
3457
  size: "small",
@@ -3425,7 +3460,7 @@ var init_TeamUsage = __esm({
3425
3460
  sx: { textTransform: "none" }
3426
3461
  },
3427
3462
  "Edit"
3428
- ), /* @__PURE__ */ import_react9.default.createElement(
3463
+ ), /* @__PURE__ */ import_react10.default.createElement(
3429
3464
  import_IconButton5.default,
3430
3465
  {
3431
3466
  size: "small",
@@ -3438,8 +3473,8 @@ var init_TeamUsage = __esm({
3438
3473
  transition: theme.transitions.create("transform")
3439
3474
  })
3440
3475
  },
3441
- /* @__PURE__ */ import_react9.default.createElement(import_icons_material6.ExpandMore, null)
3442
- )), /* @__PURE__ */ import_react9.default.createElement(
3476
+ /* @__PURE__ */ import_react10.default.createElement(import_icons_material6.ExpandMore, null)
3477
+ )), /* @__PURE__ */ import_react10.default.createElement(
3443
3478
  import_Box9.default,
3444
3479
  {
3445
3480
  sx: {
@@ -3450,20 +3485,20 @@ var init_TeamUsage = __esm({
3450
3485
  maxWidth: 640
3451
3486
  }
3452
3487
  },
3453
- /* @__PURE__ */ import_react9.default.createElement(Stat, { label: "Members", value: team.members_with_roles?.length ?? "\u2014" }),
3454
- /* @__PURE__ */ import_react9.default.createElement(Stat, { label: "Models", value: team.models?.length ? team.models.length : "All" }),
3455
- /* @__PURE__ */ import_react9.default.createElement(Stat, { label: "Budget", value: budgetStatValue(hidden, budget) }),
3456
- /* @__PURE__ */ import_react9.default.createElement(Stat, { label: "Spend", value: hidden ? "\u2014" : fmtUsd2(spend) }),
3457
- /* @__PURE__ */ import_react9.default.createElement(Stat, { label: "TPM", value: team.tpm_limit && team.tpm_limit > 0 ? team.tpm_limit.toLocaleString() : "\u2014" }),
3458
- /* @__PURE__ */ import_react9.default.createElement(Stat, { label: "RPM", value: team.rpm_limit && team.rpm_limit > 0 ? team.rpm_limit.toLocaleString() : "\u2014" })
3459
- ), hidden && /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { mt: 2, maxWidth: 640 }, /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { display: "flex", justifyContent: "space-between", alignItems: "baseline", mb: 0.75 }, /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, budgetPct.toFixed(0), "% used"), /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary" }, "Hidden by admin")), /* @__PURE__ */ import_react9.default.createElement(Meter, { value: budgetPct, tone: budgetTone3(isOver, isNear), height: 5 }), /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary", sx: { display: "block", mt: 0.75 } }, "Team budget is hidden \u2014 showing usage level only", team.budget_duration ? ` \xB7 resets every ${team.budget_duration}` : "", ".")), !hidden && budget > 0 && /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { mt: 2, maxWidth: 640 }, /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { display: "flex", justifyContent: "space-between", alignItems: "baseline", mb: 0.75 }, /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, fmtUsd2(spend), " of ", fmtUsd2(budget)), /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, budgetPct.toFixed(0), "%")), /* @__PURE__ */ import_react9.default.createElement(Meter, { value: budgetPct, tone: budgetTone3(isOver, isNear), height: 5 })), /* @__PURE__ */ import_react9.default.createElement(import_Collapse2.default, { in: expanded, unmountOnExit: true }, /* @__PURE__ */ import_react9.default.createElement(import_Divider3.default, { sx: { my: 2.5 } }), /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { mb: 2.5 }, sectionLabel("Models"), team.models?.length ? /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { display: "flex", gap: 0.5, flexWrap: "wrap" }, team.models.map((m) => /* @__PURE__ */ import_react9.default.createElement(TagChip, { key: m, label: m, title: m }))) : /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "body2", color: "text.secondary" }, "All models allowed")), renderDailySpendSection(), /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, null, sectionLabel("Members"), team.members_with_roles?.length ? /* @__PURE__ */ import_react9.default.createElement(
3488
+ /* @__PURE__ */ import_react10.default.createElement(Stat, { label: "Members", value: team.members_with_roles?.length ?? "\u2014" }),
3489
+ /* @__PURE__ */ import_react10.default.createElement(Stat, { label: "Models", value: team.models?.length ? team.models.length : "All" }),
3490
+ /* @__PURE__ */ import_react10.default.createElement(Stat, { label: "Budget", value: budgetStatValue(hidden, budget) }),
3491
+ /* @__PURE__ */ import_react10.default.createElement(Stat, { label: "Spend", value: hidden ? "\u2014" : fmtUsd2(spend) }),
3492
+ /* @__PURE__ */ import_react10.default.createElement(Stat, { label: "TPM", value: team.tpm_limit && team.tpm_limit > 0 ? team.tpm_limit.toLocaleString() : "\u2014" }),
3493
+ /* @__PURE__ */ import_react10.default.createElement(Stat, { label: "RPM", value: team.rpm_limit && team.rpm_limit > 0 ? team.rpm_limit.toLocaleString() : "\u2014" })
3494
+ ), hidden && /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { mt: 2, maxWidth: 640 }, /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { display: "flex", justifyContent: "space-between", alignItems: "baseline", mb: 0.75 }, /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, budgetPct.toFixed(0), "% used"), /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary" }, "Hidden by admin")), /* @__PURE__ */ import_react10.default.createElement(Meter, { value: budgetPct, tone: budgetTone3(isOver, isNear), height: 5 }), /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary", sx: { display: "block", mt: 0.75 } }, "Team budget is hidden \u2014 showing usage level only", team.budget_duration ? ` \xB7 resets every ${team.budget_duration}` : "", ".")), !hidden && budget > 0 && /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { mt: 2, maxWidth: 640 }, /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { display: "flex", justifyContent: "space-between", alignItems: "baseline", mb: 0.75 }, /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, fmtUsd2(spend), " of ", fmtUsd2(budget)), /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "caption", color: "text.secondary", sx: { fontVariantNumeric: "tabular-nums" } }, budgetPct.toFixed(0), "%")), /* @__PURE__ */ import_react10.default.createElement(Meter, { value: budgetPct, tone: budgetTone3(isOver, isNear), height: 5 })), /* @__PURE__ */ import_react10.default.createElement(import_Collapse2.default, { in: expanded, unmountOnExit: true }, /* @__PURE__ */ import_react10.default.createElement(import_Divider3.default, { sx: { my: 2.5 } }), /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { mb: 2.5 }, sectionLabel("Models"), team.models?.length ? /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { display: "flex", gap: 0.5, flexWrap: "wrap" }, team.models.map((m) => /* @__PURE__ */ import_react10.default.createElement(TagChip, { key: m, label: m, title: m }))) : /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "body2", color: "text.secondary" }, "All models allowed")), renderDailySpendSection(), /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, null, sectionLabel("Members"), team.members_with_roles?.length ? /* @__PURE__ */ import_react10.default.createElement(
3460
3495
  import_TableContainer4.default,
3461
3496
  {
3462
3497
  component: import_Paper7.default,
3463
3498
  variant: "outlined",
3464
3499
  sx: { borderRadius: 1.5 }
3465
3500
  },
3466
- /* @__PURE__ */ import_react9.default.createElement(import_Table4.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react9.default.createElement(import_TableHead4.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableRow4.default, null, /* @__PURE__ */ import_react9.default.createElement(import_TableCell4.default, null, "User"), /* @__PURE__ */ import_react9.default.createElement(import_TableCell4.default, { align: "right" }, "Role"))), /* @__PURE__ */ import_react9.default.createElement(import_TableBody4.default, null, team.members_with_roles.map((m) => /* @__PURE__ */ import_react9.default.createElement(import_TableRow4.default, { key: m.user_id }, /* @__PURE__ */ import_react9.default.createElement(import_TableCell4.default, null, m.user_email ? /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "body2" }, m.user_email), /* @__PURE__ */ import_react9.default.createElement(
3501
+ /* @__PURE__ */ import_react10.default.createElement(import_Table4.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react10.default.createElement(import_TableHead4.default, null, /* @__PURE__ */ import_react10.default.createElement(import_TableRow4.default, null, /* @__PURE__ */ import_react10.default.createElement(import_TableCell4.default, null, "User"), /* @__PURE__ */ import_react10.default.createElement(import_TableCell4.default, { align: "right" }, "Role"))), /* @__PURE__ */ import_react10.default.createElement(import_TableBody4.default, null, team.members_with_roles.map((m) => /* @__PURE__ */ import_react10.default.createElement(import_TableRow4.default, { key: m.user_id }, /* @__PURE__ */ import_react10.default.createElement(import_TableCell4.default, null, m.user_email ? /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "body2" }, m.user_email), /* @__PURE__ */ import_react10.default.createElement(
3467
3502
  import_Typography9.default,
3468
3503
  {
3469
3504
  variant: "caption",
@@ -3471,14 +3506,14 @@ var init_TeamUsage = __esm({
3471
3506
  sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 }
3472
3507
  },
3473
3508
  m.user_id
3474
- )) : /* @__PURE__ */ import_react9.default.createElement(
3509
+ )) : /* @__PURE__ */ import_react10.default.createElement(
3475
3510
  import_Typography9.default,
3476
3511
  {
3477
3512
  variant: "body2",
3478
3513
  sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" }
3479
3514
  },
3480
3515
  m.user_id
3481
- )), /* @__PURE__ */ import_react9.default.createElement(import_TableCell4.default, { align: "right" }, /* @__PURE__ */ import_react9.default.createElement(
3516
+ )), /* @__PURE__ */ import_react10.default.createElement(import_TableCell4.default, { align: "right" }, /* @__PURE__ */ import_react10.default.createElement(
3482
3517
  StatusPill,
3483
3518
  {
3484
3519
  label: m.role,
@@ -3486,7 +3521,7 @@ var init_TeamUsage = __esm({
3486
3521
  dot: false
3487
3522
  }
3488
3523
  ))))))
3489
- ) : /* @__PURE__ */ import_react9.default.createElement(import_Typography9.default, { variant: "body2", color: "text.secondary" }, "No members assigned."))));
3524
+ ) : /* @__PURE__ */ import_react10.default.createElement(import_Typography9.default, { variant: "body2", color: "text.secondary" }, "No members assigned."))));
3490
3525
  };
3491
3526
  TeamUsage = ({
3492
3527
  teams,
@@ -3498,22 +3533,22 @@ var init_TeamUsage = __esm({
3498
3533
  canCreate,
3499
3534
  onCreateTeam
3500
3535
  }) => {
3501
- const createAction = canCreate && onCreateTeam ? /* @__PURE__ */ import_react9.default.createElement(
3536
+ const createAction = canCreate && onCreateTeam ? /* @__PURE__ */ import_react10.default.createElement(
3502
3537
  import_Button5.default,
3503
3538
  {
3504
3539
  variant: "contained",
3505
3540
  color: "primary",
3506
3541
  disableElevation: true,
3507
- startIcon: /* @__PURE__ */ import_react9.default.createElement(import_icons_material6.Add, null),
3542
+ startIcon: /* @__PURE__ */ import_react10.default.createElement(import_icons_material6.Add, null),
3508
3543
  onClick: onCreateTeam
3509
3544
  },
3510
3545
  "Create Team"
3511
3546
  ) : void 0;
3512
3547
  if (loading) {
3513
- return /* @__PURE__ */ import_react9.default.createElement(SectionCard, { title: "Teams", actions: createAction }, /* @__PURE__ */ import_react9.default.createElement(import_Skeleton4.default, { variant: "rounded", height: 120, sx: { mb: 2 } }), /* @__PURE__ */ import_react9.default.createElement(import_Skeleton4.default, { variant: "rounded", height: 120 }));
3548
+ return /* @__PURE__ */ import_react10.default.createElement(SectionCard, { title: "Teams", actions: createAction }, /* @__PURE__ */ import_react10.default.createElement(import_Skeleton4.default, { variant: "rounded", height: 120, sx: { mb: 2 } }), /* @__PURE__ */ import_react10.default.createElement(import_Skeleton4.default, { variant: "rounded", height: 120 }));
3514
3549
  }
3515
3550
  if (!teams.length) {
3516
- return /* @__PURE__ */ import_react9.default.createElement(SectionCard, { title: "Teams", actions: createAction }, /* @__PURE__ */ import_react9.default.createElement(
3551
+ return /* @__PURE__ */ import_react10.default.createElement(SectionCard, { title: "Teams", actions: createAction }, /* @__PURE__ */ import_react10.default.createElement(
3517
3552
  EmptyState,
3518
3553
  {
3519
3554
  message: "You're not a member of any LiteLLM team yet.",
@@ -3521,14 +3556,14 @@ var init_TeamUsage = __esm({
3521
3556
  }
3522
3557
  ));
3523
3558
  }
3524
- return /* @__PURE__ */ import_react9.default.createElement(
3559
+ return /* @__PURE__ */ import_react10.default.createElement(
3525
3560
  SectionCard,
3526
3561
  {
3527
3562
  title: "Teams",
3528
3563
  subtitle: `${teams.length} team${teams.length === 1 ? "" : "s"}`,
3529
3564
  actions: createAction
3530
3565
  },
3531
- /* @__PURE__ */ import_react9.default.createElement(import_Box9.default, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, teams.map((team) => /* @__PURE__ */ import_react9.default.createElement(
3566
+ /* @__PURE__ */ import_react10.default.createElement(import_Box9.default, { sx: { display: "flex", flexDirection: "column", gap: 2 } }, teams.map((team) => /* @__PURE__ */ import_react10.default.createElement(
3532
3567
  TeamCard,
3533
3568
  {
3534
3569
  key: team.team_id,
@@ -3562,11 +3597,11 @@ function fmtTokens(n) {
3562
3597
  if (n >= 1e3) return `${(n / 1e3).toFixed(0)}K`;
3563
3598
  return String(n);
3564
3599
  }
3565
- var import_react10, import_Box10, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_TableSortLabel2, import_Typography10, import_MenuItem4, import_Select, import_FormControl, import_InputLabel, import_TextField5, import_InputAdornment2, import_icons_material7, import_ContentCopy, import_Tooltip, import_Snackbar, import_Alert4, import_styles7, ALL_PROXY_MODELS2, ModelsTable;
3600
+ var import_react11, import_Box10, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_TableSortLabel2, import_Typography10, import_MenuItem4, import_Select, import_FormControl, import_InputLabel, import_TextField5, import_InputAdornment2, import_icons_material7, import_ContentCopy, import_Tooltip, import_Snackbar, import_Alert4, import_styles7, ALL_PROXY_MODELS2, ModelsTable;
3566
3601
  var init_ModelsTable = __esm({
3567
3602
  "src/components/ModelsTable.tsx"() {
3568
3603
  "use strict";
3569
- import_react10 = __toESM(require("react"));
3604
+ import_react11 = __toESM(require("react"));
3570
3605
  import_Box10 = __toESM(require("@mui/material/Box"));
3571
3606
  import_Table5 = __toESM(require("@mui/material/Table"));
3572
3607
  import_TableBody5 = __toESM(require("@mui/material/TableBody"));
@@ -3592,20 +3627,20 @@ var init_ModelsTable = __esm({
3592
3627
  ALL_PROXY_MODELS2 = "all-proxy-models";
3593
3628
  ModelsTable = ({ allModels, teams, loading }) => {
3594
3629
  const theme = (0, import_styles7.useTheme)();
3595
- const [selectedTeamId, setSelectedTeamId] = (0, import_react10.useState)("");
3596
- const [filterText, setFilterText] = (0, import_react10.useState)("");
3597
- const [copiedSnackbar, setCopiedSnackbar] = (0, import_react10.useState)(false);
3598
- const [sortKey, setSortKey] = (0, import_react10.useState)("model_name");
3599
- const [sortDirection, setSortDirection] = (0, import_react10.useState)("asc");
3600
- const selectedTeam = (0, import_react10.useMemo)(
3630
+ const [selectedTeamId, setSelectedTeamId] = (0, import_react11.useState)("");
3631
+ const [filterText, setFilterText] = (0, import_react11.useState)("");
3632
+ const [copiedSnackbar, setCopiedSnackbar] = (0, import_react11.useState)(false);
3633
+ const [sortKey, setSortKey] = (0, import_react11.useState)("model_name");
3634
+ const [sortDirection, setSortDirection] = (0, import_react11.useState)("asc");
3635
+ const selectedTeam = (0, import_react11.useMemo)(
3601
3636
  () => teams.find((t) => t.team_id === selectedTeamId) ?? null,
3602
3637
  [teams, selectedTeamId]
3603
3638
  );
3604
- const teamModels = (0, import_react10.useMemo)(() => {
3639
+ const teamModels = (0, import_react11.useMemo)(() => {
3605
3640
  if (!selectedTeam) return [];
3606
3641
  return allModels.filter((model) => isModelAllowedByTeam2(model, selectedTeam.models));
3607
3642
  }, [allModels, selectedTeam]);
3608
- const filteredModels = (0, import_react10.useMemo)(() => {
3643
+ const filteredModels = (0, import_react11.useMemo)(() => {
3609
3644
  const q = filterText.trim().toLowerCase();
3610
3645
  let models = teamModels;
3611
3646
  if (q) {
@@ -3652,10 +3687,10 @@ var init_ModelsTable = __esm({
3652
3687
  return sortDirection === "asc" ? aVal - bVal : bVal - aVal;
3653
3688
  });
3654
3689
  }, [teamModels, filterText, sortKey, sortDirection]);
3655
- const handleCopyModelId = (0, import_react10.useCallback)((modelId) => {
3690
+ const handleCopyModelId = (0, import_react11.useCallback)((modelId) => {
3656
3691
  navigator.clipboard.writeText(modelId).then(() => setCopiedSnackbar(true));
3657
3692
  }, []);
3658
- const handleSort = (0, import_react10.useCallback)((key) => {
3693
+ const handleSort = (0, import_react11.useCallback)((key) => {
3659
3694
  if (sortKey === key) {
3660
3695
  setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
3661
3696
  } else {
@@ -3677,13 +3712,13 @@ var init_ModelsTable = __esm({
3677
3712
  return theme.palette.info.main;
3678
3713
  }
3679
3714
  };
3680
- return /* @__PURE__ */ import_react10.default.createElement(
3715
+ return /* @__PURE__ */ import_react11.default.createElement(
3681
3716
  SectionCard,
3682
3717
  {
3683
3718
  title: "Available Models",
3684
3719
  subtitle: selectedTeam ? `${filteredModels.length}${filterText.trim() ? ` of ${teamModels.length}` : ""} model${filteredModels.length === 1 ? "" : "s"}` : "Select a team to view its models"
3685
3720
  },
3686
- /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { sx: { px: 2.5, pb: 2.5, pt: 1, display: "flex", gap: 2, flexWrap: "wrap" } }, /* @__PURE__ */ import_react10.default.createElement(import_FormControl.default, { size: "small", sx: { minWidth: 240, mb: 2 } }, /* @__PURE__ */ import_react10.default.createElement(import_InputLabel.default, { id: "team-select-label" }, "Team"), /* @__PURE__ */ import_react10.default.createElement(
3721
+ /* @__PURE__ */ import_react11.default.createElement(import_Box10.default, { sx: { px: 2.5, pb: 2.5, pt: 1, display: "flex", gap: 2, flexWrap: "wrap" } }, /* @__PURE__ */ import_react11.default.createElement(import_FormControl.default, { size: "small", sx: { minWidth: 240, mb: 2 } }, /* @__PURE__ */ import_react11.default.createElement(import_InputLabel.default, { id: "team-select-label" }, "Team"), /* @__PURE__ */ import_react11.default.createElement(
3687
3722
  import_Select.default,
3688
3723
  {
3689
3724
  labelId: "team-select-label",
@@ -3691,8 +3726,8 @@ var init_ModelsTable = __esm({
3691
3726
  label: "Team",
3692
3727
  onChange: (e) => setSelectedTeamId(e.target.value)
3693
3728
  },
3694
- teams.map((t) => /* @__PURE__ */ import_react10.default.createElement(import_MenuItem4.default, { key: t.team_id, value: t.team_id }, t.team_alias ?? t.team_id))
3695
- )), /* @__PURE__ */ import_react10.default.createElement(
3729
+ teams.map((t) => /* @__PURE__ */ import_react11.default.createElement(import_MenuItem4.default, { key: t.team_id, value: t.team_id }, t.team_alias ?? t.team_id))
3730
+ )), /* @__PURE__ */ import_react11.default.createElement(
3696
3731
  import_TextField5.default,
3697
3732
  {
3698
3733
  label: "Filter Models",
@@ -3702,33 +3737,33 @@ var init_ModelsTable = __esm({
3702
3737
  disabled: !selectedTeamId,
3703
3738
  sx: { minWidth: 240, mb: 2 },
3704
3739
  InputProps: {
3705
- startAdornment: /* @__PURE__ */ import_react10.default.createElement(import_InputAdornment2.default, { position: "start" }, /* @__PURE__ */ import_react10.default.createElement(import_icons_material7.Search, { fontSize: "small" }))
3740
+ startAdornment: /* @__PURE__ */ import_react11.default.createElement(import_InputAdornment2.default, { position: "start" }, /* @__PURE__ */ import_react11.default.createElement(import_icons_material7.Search, { fontSize: "small" }))
3706
3741
  }
3707
3742
  }
3708
3743
  )),
3709
- loading && /* @__PURE__ */ import_react10.default.createElement(EmptyState, { message: "Loading models\u2026" }),
3710
- !loading && !selectedTeamId && /* @__PURE__ */ import_react10.default.createElement(
3744
+ loading && /* @__PURE__ */ import_react11.default.createElement(EmptyState, { message: "Loading models\u2026" }),
3745
+ !loading && !selectedTeamId && /* @__PURE__ */ import_react11.default.createElement(
3711
3746
  EmptyState,
3712
3747
  {
3713
3748
  message: "Select a team to see available models",
3714
3749
  hint: "Each team may have a different set of models assigned"
3715
3750
  }
3716
3751
  ),
3717
- !loading && selectedTeamId && teamModels.length === 0 && /* @__PURE__ */ import_react10.default.createElement(
3752
+ !loading && selectedTeamId && teamModels.length === 0 && /* @__PURE__ */ import_react11.default.createElement(
3718
3753
  EmptyState,
3719
3754
  {
3720
3755
  message: "No models available for this team",
3721
3756
  hint: allModels.length === 0 ? "No models are configured in the system" : "None of the team's assigned models were found in the catalog"
3722
3757
  }
3723
3758
  ),
3724
- !loading && selectedTeamId && teamModels.length > 0 && filteredModels.length === 0 && /* @__PURE__ */ import_react10.default.createElement(
3759
+ !loading && selectedTeamId && teamModels.length > 0 && filteredModels.length === 0 && /* @__PURE__ */ import_react11.default.createElement(
3725
3760
  EmptyState,
3726
3761
  {
3727
3762
  message: "No models match your search",
3728
3763
  hint: "Try a different search term"
3729
3764
  }
3730
3765
  ),
3731
- !loading && filteredModels.length > 0 && /* @__PURE__ */ import_react10.default.createElement(import_TableContainer5.default, null, /* @__PURE__ */ import_react10.default.createElement(import_Table5.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react10.default.createElement(import_TableHead5.default, null, /* @__PURE__ */ import_react10.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { sortDirection: sortKey === "model_name" ? sortDirection : false }, /* @__PURE__ */ import_react10.default.createElement(import_TableSortLabel2.default, { active: sortKey === "model_name", direction: sortKey === "model_name" ? sortDirection : "asc", onClick: () => handleSort("model_name") }, "Model ID")), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { sortDirection: sortKey === "mode" ? sortDirection : false }, /* @__PURE__ */ import_react10.default.createElement(import_TableSortLabel2.default, { active: sortKey === "mode", direction: sortKey === "mode" ? sortDirection : "asc", onClick: () => handleSort("mode") }, "Mode")), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { align: "right", sortDirection: sortKey === "input_cost_per_token" ? sortDirection : false }, /* @__PURE__ */ import_react10.default.createElement(import_TableSortLabel2.default, { active: sortKey === "input_cost_per_token", direction: sortKey === "input_cost_per_token" ? sortDirection : "asc", onClick: () => handleSort("input_cost_per_token") }, "Input Cost")), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { align: "right", sortDirection: sortKey === "output_cost_per_token" ? sortDirection : false }, /* @__PURE__ */ import_react10.default.createElement(import_TableSortLabel2.default, { active: sortKey === "output_cost_per_token", direction: sortKey === "output_cost_per_token" ? sortDirection : "asc", onClick: () => handleSort("output_cost_per_token") }, "Output Cost")), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { align: "right", sortDirection: sortKey === "max_input_tokens" ? sortDirection : false }, /* @__PURE__ */ import_react10.default.createElement(import_TableSortLabel2.default, { active: sortKey === "max_input_tokens", direction: sortKey === "max_input_tokens" ? sortDirection : "asc", onClick: () => handleSort("max_input_tokens") }, "Max Input")), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { align: "right", sortDirection: sortKey === "max_output_tokens" ? sortDirection : false }, /* @__PURE__ */ import_react10.default.createElement(import_TableSortLabel2.default, { active: sortKey === "max_output_tokens", direction: sortKey === "max_output_tokens" ? sortDirection : "asc", onClick: () => handleSort("max_output_tokens") }, "Max Output")), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, null, "Capabilities"))), /* @__PURE__ */ import_react10.default.createElement(import_TableBody5.default, null, filteredModels.map((m) => /* @__PURE__ */ import_react10.default.createElement(import_TableRow5.default, { key: m.model_name, hover: true }, /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ import_react10.default.createElement(import_Tooltip.default, { title: m.model_name, placement: "top" }, /* @__PURE__ */ import_react10.default.createElement(
3766
+ !loading && filteredModels.length > 0 && /* @__PURE__ */ import_react11.default.createElement(import_TableContainer5.default, null, /* @__PURE__ */ import_react11.default.createElement(import_Table5.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react11.default.createElement(import_TableHead5.default, null, /* @__PURE__ */ import_react11.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { sortDirection: sortKey === "model_name" ? sortDirection : false }, /* @__PURE__ */ import_react11.default.createElement(import_TableSortLabel2.default, { active: sortKey === "model_name", direction: sortKey === "model_name" ? sortDirection : "asc", onClick: () => handleSort("model_name") }, "Model ID")), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { sortDirection: sortKey === "mode" ? sortDirection : false }, /* @__PURE__ */ import_react11.default.createElement(import_TableSortLabel2.default, { active: sortKey === "mode", direction: sortKey === "mode" ? sortDirection : "asc", onClick: () => handleSort("mode") }, "Mode")), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { align: "right", sortDirection: sortKey === "input_cost_per_token" ? sortDirection : false }, /* @__PURE__ */ import_react11.default.createElement(import_TableSortLabel2.default, { active: sortKey === "input_cost_per_token", direction: sortKey === "input_cost_per_token" ? sortDirection : "asc", onClick: () => handleSort("input_cost_per_token") }, "Input Cost")), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { align: "right", sortDirection: sortKey === "output_cost_per_token" ? sortDirection : false }, /* @__PURE__ */ import_react11.default.createElement(import_TableSortLabel2.default, { active: sortKey === "output_cost_per_token", direction: sortKey === "output_cost_per_token" ? sortDirection : "asc", onClick: () => handleSort("output_cost_per_token") }, "Output Cost")), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { align: "right", sortDirection: sortKey === "max_input_tokens" ? sortDirection : false }, /* @__PURE__ */ import_react11.default.createElement(import_TableSortLabel2.default, { active: sortKey === "max_input_tokens", direction: sortKey === "max_input_tokens" ? sortDirection : "asc", onClick: () => handleSort("max_input_tokens") }, "Max Input")), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { align: "right", sortDirection: sortKey === "max_output_tokens" ? sortDirection : false }, /* @__PURE__ */ import_react11.default.createElement(import_TableSortLabel2.default, { active: sortKey === "max_output_tokens", direction: sortKey === "max_output_tokens" ? sortDirection : "asc", onClick: () => handleSort("max_output_tokens") }, "Max Output")), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, null, "Capabilities"))), /* @__PURE__ */ import_react11.default.createElement(import_TableBody5.default, null, filteredModels.map((m) => /* @__PURE__ */ import_react11.default.createElement(import_TableRow5.default, { key: m.model_name, hover: true }, /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react11.default.createElement(import_Box10.default, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ import_react11.default.createElement(import_Tooltip.default, { title: m.model_name, placement: "top" }, /* @__PURE__ */ import_react11.default.createElement(
3732
3767
  "span",
3733
3768
  {
3734
3769
  role: "button",
@@ -3738,8 +3773,8 @@ var init_ModelsTable = __esm({
3738
3773
  onKeyDown: (e) => e.key === "Enter" && handleCopyModelId(m.model_name),
3739
3774
  style: { cursor: "pointer", display: "inline-flex" }
3740
3775
  },
3741
- /* @__PURE__ */ import_react10.default.createElement(TagChip, { label: m.model_name, title: "Copy model ID" })
3742
- )), /* @__PURE__ */ import_react10.default.createElement(import_Tooltip.default, { title: "Copy model ID" }, /* @__PURE__ */ import_react10.default.createElement(
3776
+ /* @__PURE__ */ import_react11.default.createElement(TagChip, { label: m.model_name, title: "Copy model ID" })
3777
+ )), /* @__PURE__ */ import_react11.default.createElement(import_Tooltip.default, { title: "Copy model ID" }, /* @__PURE__ */ import_react11.default.createElement(
3743
3778
  import_Box10.default,
3744
3779
  {
3745
3780
  component: "span",
@@ -3750,8 +3785,8 @@ var init_ModelsTable = __esm({
3750
3785
  sx: quietIconButtonSx("accent"),
3751
3786
  style: { cursor: "pointer", display: "inline-flex" }
3752
3787
  },
3753
- /* @__PURE__ */ import_react10.default.createElement(import_ContentCopy.default, { sx: { fontSize: 14 } })
3754
- )))), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react10.default.createElement(
3788
+ /* @__PURE__ */ import_react11.default.createElement(import_ContentCopy.default, { sx: { fontSize: 14 } })
3789
+ )))), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react11.default.createElement(
3755
3790
  import_Box10.default,
3756
3791
  {
3757
3792
  component: "span",
@@ -3768,8 +3803,8 @@ var init_ModelsTable = __esm({
3768
3803
  }
3769
3804
  },
3770
3805
  m.mode
3771
- )), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtCostPerToken(m.input_cost_per_token))), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtCostPerToken(m.output_cost_per_token))), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtTokens(m.max_input_tokens))), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react10.default.createElement(import_Typography10.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtTokens(m.max_output_tokens))), /* @__PURE__ */ import_react10.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react10.default.createElement(import_Box10.default, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap" } }, m.supports_function_calling && /* @__PURE__ */ import_react10.default.createElement(TagChip, { label: "Fn", title: "Function calling" }), m.supports_vision && /* @__PURE__ */ import_react10.default.createElement(TagChip, { label: "\u{1F441}", title: "Vision" })))))))),
3772
- /* @__PURE__ */ import_react10.default.createElement(
3806
+ )), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react11.default.createElement(import_Typography10.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtCostPerToken(m.input_cost_per_token))), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react11.default.createElement(import_Typography10.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtCostPerToken(m.output_cost_per_token))), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react11.default.createElement(import_Typography10.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtTokens(m.max_input_tokens))), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, { align: "right" }, /* @__PURE__ */ import_react11.default.createElement(import_Typography10.default, { variant: "body2", sx: { fontVariantNumeric: "tabular-nums" } }, fmtTokens(m.max_output_tokens))), /* @__PURE__ */ import_react11.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react11.default.createElement(import_Box10.default, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap" } }, m.supports_function_calling && /* @__PURE__ */ import_react11.default.createElement(TagChip, { label: "Fn", title: "Function calling" }), m.supports_vision && /* @__PURE__ */ import_react11.default.createElement(TagChip, { label: "\u{1F441}", title: "Vision" })))))))),
3807
+ /* @__PURE__ */ import_react11.default.createElement(
3773
3808
  import_Snackbar.default,
3774
3809
  {
3775
3810
  open: copiedSnackbar,
@@ -3777,7 +3812,7 @@ var init_ModelsTable = __esm({
3777
3812
  onClose: () => setCopiedSnackbar(false),
3778
3813
  anchorOrigin: { vertical: "bottom", horizontal: "center" }
3779
3814
  },
3780
- /* @__PURE__ */ import_react10.default.createElement(import_Alert4.default, { severity: "success", variant: "filled", sx: { fontSize: 13 } }, "Model ID copied to clipboard")
3815
+ /* @__PURE__ */ import_react11.default.createElement(import_Alert4.default, { severity: "success", variant: "filled", sx: { fontSize: 13 } }, "Model ID copied to clipboard")
3781
3816
  )
3782
3817
  );
3783
3818
  };
@@ -3805,10 +3840,10 @@ function formatDateTime(iso) {
3805
3840
  }
3806
3841
  function renderAuditLogBody(loading, entries) {
3807
3842
  if (loading) {
3808
- return /* @__PURE__ */ import_react11.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, { colSpan: 6, sx: { py: 2 } }, /* @__PURE__ */ import_react11.default.createElement(import_Skeleton5.default, { variant: "rounded", height: 160 })));
3843
+ return /* @__PURE__ */ import_react12.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, { colSpan: 6, sx: { py: 2 } }, /* @__PURE__ */ import_react12.default.createElement(import_Skeleton5.default, { variant: "rounded", height: 160 })));
3809
3844
  }
3810
3845
  if (entries.length === 0) {
3811
- return /* @__PURE__ */ import_react11.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, { colSpan: 6 }, /* @__PURE__ */ import_react11.default.createElement(
3846
+ return /* @__PURE__ */ import_react12.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, { colSpan: 6 }, /* @__PURE__ */ import_react12.default.createElement(
3812
3847
  EmptyState,
3813
3848
  {
3814
3849
  message: "No audit events found",
@@ -3816,13 +3851,13 @@ function renderAuditLogBody(loading, entries) {
3816
3851
  }
3817
3852
  )));
3818
3853
  }
3819
- return entries.map((entry) => /* @__PURE__ */ import_react11.default.createElement(DetailRow, { key: entry.id, entry }));
3854
+ return entries.map((entry) => /* @__PURE__ */ import_react12.default.createElement(DetailRow, { key: entry.id, entry }));
3820
3855
  }
3821
- var import_react11, import_Box11, import_Typography11, import_Table6, import_TableBody6, import_TableCell6, import_TableContainer6, import_TableHead6, import_TableRow6, import_TablePagination, import_TextField6, import_MenuItem5, import_Skeleton5, import_Collapse3, import_IconButton6, import_Alert5, import_styles8, import_icons_material8, import_react_use2, ACTION_TONES, TABLE_LABELS, DetailRow, AuditLog;
3856
+ var import_react12, import_Box11, import_Typography11, import_Table6, import_TableBody6, import_TableCell6, import_TableContainer6, import_TableHead6, import_TableRow6, import_TablePagination, import_TextField6, import_MenuItem5, import_Skeleton5, import_Collapse3, import_IconButton6, import_Alert5, import_styles8, import_icons_material8, import_react_use2, ACTION_TONES, TABLE_LABELS, DetailRow, AuditLog;
3822
3857
  var init_AuditLog = __esm({
3823
3858
  "src/components/AuditLog.tsx"() {
3824
3859
  "use strict";
3825
- import_react11 = __toESM(require("react"));
3860
+ import_react12 = __toESM(require("react"));
3826
3861
  import_Box11 = __toESM(require("@mui/material/Box"));
3827
3862
  import_Typography11 = __toESM(require("@mui/material/Typography"));
3828
3863
  import_Table6 = __toESM(require("@mui/material/Table"));
@@ -3857,9 +3892,9 @@ var init_AuditLog = __esm({
3857
3892
  LiteLLM_UserTable: "User"
3858
3893
  };
3859
3894
  DetailRow = ({ entry }) => {
3860
- const [open, setOpen] = (0, import_react11.useState)(false);
3895
+ const [open, setOpen] = (0, import_react12.useState)(false);
3861
3896
  const hasDetail = entry.before_value || entry.updated_values;
3862
- return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, { sx: { width: 40, pr: 0 } }, hasDetail && /* @__PURE__ */ import_react11.default.createElement(
3897
+ return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, { sx: { width: 40, pr: 0 } }, hasDetail && /* @__PURE__ */ import_react12.default.createElement(
3863
3898
  import_IconButton6.default,
3864
3899
  {
3865
3900
  size: "small",
@@ -3872,8 +3907,8 @@ var init_AuditLog = __esm({
3872
3907
  transition: theme.transitions.create("transform")
3873
3908
  })
3874
3909
  },
3875
- /* @__PURE__ */ import_react11.default.createElement(import_icons_material8.KeyboardArrowDown, { fontSize: "small" })
3876
- )), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, { sx: { whiteSpace: "nowrap" } }, /* @__PURE__ */ import_react11.default.createElement(import_Typography11.default, { variant: "body2", color: "text.secondary" }, formatDateTime(entry.updated_at))), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, entry.action && /* @__PURE__ */ import_react11.default.createElement(StatusPill, { label: entry.action, tone: actionTone(entry.action) })), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, /* @__PURE__ */ import_react11.default.createElement(import_Typography11.default, { variant: "body2" }, prettyTableName(entry.table_name))), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, /* @__PURE__ */ import_react11.default.createElement(
3910
+ /* @__PURE__ */ import_react12.default.createElement(import_icons_material8.KeyboardArrowDown, { fontSize: "small" })
3911
+ )), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, { sx: { whiteSpace: "nowrap" } }, /* @__PURE__ */ import_react12.default.createElement(import_Typography11.default, { variant: "body2", color: "text.secondary" }, formatDateTime(entry.updated_at))), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, entry.action && /* @__PURE__ */ import_react12.default.createElement(StatusPill, { label: entry.action, tone: actionTone(entry.action) })), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, /* @__PURE__ */ import_react12.default.createElement(import_Typography11.default, { variant: "body2" }, prettyTableName(entry.table_name))), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, /* @__PURE__ */ import_react12.default.createElement(
3877
3912
  import_Typography11.default,
3878
3913
  {
3879
3914
  variant: "body2",
@@ -3883,7 +3918,7 @@ var init_AuditLog = __esm({
3883
3918
  sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 12 }
3884
3919
  },
3885
3920
  entry.object_id ? entry.object_id.slice(0, 20) + (entry.object_id.length > 20 ? "\u2026" : "") : "\u2014"
3886
- )), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, entry.changed_by ?? "\u2014")), hasDetail && /* @__PURE__ */ import_react11.default.createElement(import_TableRow6.default, { sx: { "&&:hover": { bgcolor: "transparent" } } }, /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, { colSpan: 6, sx: { "&&": { py: 0, border: 0 } } }, /* @__PURE__ */ import_react11.default.createElement(import_Collapse3.default, { in: open, unmountOnExit: true }, /* @__PURE__ */ import_react11.default.createElement(
3921
+ )), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, entry.changed_by ?? "\u2014")), hasDetail && /* @__PURE__ */ import_react12.default.createElement(import_TableRow6.default, { sx: { "&&:hover": { bgcolor: "transparent" } } }, /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, { colSpan: 6, sx: { "&&": { py: 0, border: 0 } } }, /* @__PURE__ */ import_react12.default.createElement(import_Collapse3.default, { in: open, unmountOnExit: true }, /* @__PURE__ */ import_react12.default.createElement(
3887
3922
  import_Box11.default,
3888
3923
  {
3889
3924
  display: "flex",
@@ -3896,7 +3931,7 @@ var init_AuditLog = __esm({
3896
3931
  bgcolor: (0, import_styles8.alpha)(theme.palette.text.primary, theme.palette.mode === "dark" ? 0.05 : 0.03)
3897
3932
  })
3898
3933
  },
3899
- entry.before_value && /* @__PURE__ */ import_react11.default.createElement(import_Box11.default, { flex: 1, minWidth: 200 }, /* @__PURE__ */ import_react11.default.createElement(
3934
+ entry.before_value && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { flex: 1, minWidth: 200 }, /* @__PURE__ */ import_react12.default.createElement(
3900
3935
  import_Typography11.default,
3901
3936
  {
3902
3937
  variant: "caption",
@@ -3906,8 +3941,8 @@ var init_AuditLog = __esm({
3906
3941
  sx: { fontSize: 10.5, fontWeight: 700, letterSpacing: "0.07em", textTransform: "uppercase" }
3907
3942
  },
3908
3943
  "Before"
3909
- ), /* @__PURE__ */ import_react11.default.createElement(import_Typography11.default, { component: "pre", variant: "caption", sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", whiteSpace: "pre-wrap", wordBreak: "break-all", m: 0 } }, JSON.stringify(entry.before_value, null, 2))),
3910
- entry.updated_values && /* @__PURE__ */ import_react11.default.createElement(import_Box11.default, { flex: 1, minWidth: 200 }, /* @__PURE__ */ import_react11.default.createElement(
3944
+ ), /* @__PURE__ */ import_react12.default.createElement(import_Typography11.default, { component: "pre", variant: "caption", sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", whiteSpace: "pre-wrap", wordBreak: "break-all", m: 0 } }, JSON.stringify(entry.before_value, null, 2))),
3945
+ entry.updated_values && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { flex: 1, minWidth: 200 }, /* @__PURE__ */ import_react12.default.createElement(
3911
3946
  import_Typography11.default,
3912
3947
  {
3913
3948
  variant: "caption",
@@ -3917,14 +3952,14 @@ var init_AuditLog = __esm({
3917
3952
  sx: { fontSize: 10.5, fontWeight: 700, letterSpacing: "0.07em", textTransform: "uppercase" }
3918
3953
  },
3919
3954
  "After"
3920
- ), /* @__PURE__ */ import_react11.default.createElement(import_Typography11.default, { component: "pre", variant: "caption", sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", whiteSpace: "pre-wrap", wordBreak: "break-all", m: 0 } }, JSON.stringify(entry.updated_values, null, 2)))
3955
+ ), /* @__PURE__ */ import_react12.default.createElement(import_Typography11.default, { component: "pre", variant: "caption", sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", whiteSpace: "pre-wrap", wordBreak: "break-all", m: 0 } }, JSON.stringify(entry.updated_values, null, 2)))
3921
3956
  )))));
3922
3957
  };
3923
3958
  AuditLog = ({ api }) => {
3924
- const [page, setPage] = (0, import_react11.useState)(0);
3925
- const [pageSize, setPageSize] = (0, import_react11.useState)(25);
3926
- const [filters, setFilters] = (0, import_react11.useState)({});
3927
- const fetchParams = (0, import_react11.useMemo)(
3959
+ const [page, setPage] = (0, import_react12.useState)(0);
3960
+ const [pageSize, setPageSize] = (0, import_react12.useState)(25);
3961
+ const [filters, setFilters] = (0, import_react12.useState)({});
3962
+ const fetchParams = (0, import_react12.useMemo)(
3928
3963
  () => ({ page: page + 1, page_size: pageSize, ...filters }),
3929
3964
  [page, pageSize, filters]
3930
3965
  );
@@ -3934,13 +3969,13 @@ var init_AuditLog = __esm({
3934
3969
  );
3935
3970
  const entries = value?.audit_logs ?? [];
3936
3971
  const total = value?.total ?? 0;
3937
- return /* @__PURE__ */ import_react11.default.createElement(
3972
+ return /* @__PURE__ */ import_react12.default.createElement(
3938
3973
  SectionCard,
3939
3974
  {
3940
3975
  title: "Audit Log",
3941
3976
  subtitle: loading ? "Loading\u2026" : `${total.toLocaleString()} event${total === 1 ? "" : "s"}`,
3942
3977
  flush: true,
3943
- actions: /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement(
3978
+ actions: /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement(
3944
3979
  import_TextField6.default,
3945
3980
  {
3946
3981
  size: "small",
@@ -3953,12 +3988,12 @@ var init_AuditLog = __esm({
3953
3988
  },
3954
3989
  sx: { minWidth: 150 }
3955
3990
  },
3956
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "" }, "All actions"),
3957
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "created" }, "Created"),
3958
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "updated" }, "Updated"),
3959
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "deleted" }, "Deleted"),
3960
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "blocked" }, "Blocked")
3961
- ), /* @__PURE__ */ import_react11.default.createElement(
3991
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "" }, "All actions"),
3992
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "created" }, "Created"),
3993
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "updated" }, "Updated"),
3994
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "deleted" }, "Deleted"),
3995
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "blocked" }, "Blocked")
3996
+ ), /* @__PURE__ */ import_react12.default.createElement(
3962
3997
  import_TextField6.default,
3963
3998
  {
3964
3999
  size: "small",
@@ -3971,13 +4006,13 @@ var init_AuditLog = __esm({
3971
4006
  },
3972
4007
  sx: { minWidth: 150 }
3973
4008
  },
3974
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "" }, "All tables"),
3975
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "LiteLLM_VerificationToken" }, "Key"),
3976
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "LiteLLM_TeamTable" }, "Team"),
3977
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "LiteLLM_TeamMembership" }, "Team member"),
3978
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "LiteLLM_ObjectPermissionTable" }, "Team access (KB / MCP)"),
3979
- /* @__PURE__ */ import_react11.default.createElement(import_MenuItem5.default, { value: "LiteLLM_UserTable" }, "User")
3980
- ), /* @__PURE__ */ import_react11.default.createElement(
4009
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "" }, "All tables"),
4010
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "LiteLLM_VerificationToken" }, "Key"),
4011
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "LiteLLM_TeamTable" }, "Team"),
4012
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "LiteLLM_TeamMembership" }, "Team member"),
4013
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "LiteLLM_ObjectPermissionTable" }, "Team access (KB / MCP)"),
4014
+ /* @__PURE__ */ import_react12.default.createElement(import_MenuItem5.default, { value: "LiteLLM_UserTable" }, "User")
4015
+ ), /* @__PURE__ */ import_react12.default.createElement(
3981
4016
  import_TextField6.default,
3982
4017
  {
3983
4018
  size: "small",
@@ -3991,9 +4026,9 @@ var init_AuditLog = __esm({
3991
4026
  }
3992
4027
  ))
3993
4028
  },
3994
- error && /* @__PURE__ */ import_react11.default.createElement(import_Box11.default, { px: 2.5, pb: 2 }, /* @__PURE__ */ import_react11.default.createElement(import_Alert5.default, { severity: "error" }, error.message)),
3995
- /* @__PURE__ */ import_react11.default.createElement(import_TableContainer6.default, null, /* @__PURE__ */ import_react11.default.createElement(import_Table6.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react11.default.createElement(import_TableHead6.default, null, /* @__PURE__ */ import_react11.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, { sx: { width: 40 } }), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, "Time"), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, "Action"), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, "Table"), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, "Object ID"), /* @__PURE__ */ import_react11.default.createElement(import_TableCell6.default, null, "Changed By"))), /* @__PURE__ */ import_react11.default.createElement(import_TableBody6.default, null, renderAuditLogBody(loading, entries)))),
3996
- /* @__PURE__ */ import_react11.default.createElement(
4029
+ error && /* @__PURE__ */ import_react12.default.createElement(import_Box11.default, { px: 2.5, pb: 2 }, /* @__PURE__ */ import_react12.default.createElement(import_Alert5.default, { severity: "error" }, error.message)),
4030
+ /* @__PURE__ */ import_react12.default.createElement(import_TableContainer6.default, null, /* @__PURE__ */ import_react12.default.createElement(import_Table6.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react12.default.createElement(import_TableHead6.default, null, /* @__PURE__ */ import_react12.default.createElement(import_TableRow6.default, null, /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, { sx: { width: 40 } }), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, "Time"), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, "Action"), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, "Table"), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, "Object ID"), /* @__PURE__ */ import_react12.default.createElement(import_TableCell6.default, null, "Changed By"))), /* @__PURE__ */ import_react12.default.createElement(import_TableBody6.default, null, renderAuditLogBody(loading, entries)))),
4031
+ /* @__PURE__ */ import_react12.default.createElement(
3997
4032
  import_TablePagination.default,
3998
4033
  {
3999
4034
  component: "div",
@@ -4062,11 +4097,11 @@ function initDateRange() {
4062
4097
  else start.setDate(start.getDate() - 7);
4063
4098
  return { start, end };
4064
4099
  }
4065
- var import_react12, import_Box12, import_Snackbar2, import_Alert6, import_CircularProgress6, import_Typography12, import_Paper8, import_Tabs2, import_Tab2, import_Grid2, import_react_router_dom, import_react_use3, import_core_plugin_api4, import_plugin_permission_react, PERIOD_LS_KEY2, PAGE_TABS, isPageTab, LiteLLMPage;
4100
+ var import_react13, import_Box12, import_Snackbar2, import_Alert6, import_CircularProgress6, import_Typography12, import_Paper8, import_Tabs2, import_Tab2, import_Grid2, import_react_router_dom, import_react_use3, import_core_plugin_api4, import_plugin_permission_react, PERIOD_LS_KEY2, PAGE_TABS, isPageTab, LiteLLMPage;
4066
4101
  var init_LiteLLMPage = __esm({
4067
4102
  "src/components/LiteLLMPage.tsx"() {
4068
4103
  "use strict";
4069
- import_react12 = __toESM(require("react"));
4104
+ import_react13 = __toESM(require("react"));
4070
4105
  import_Box12 = __toESM(require("@mui/material/Box"));
4071
4106
  import_Snackbar2 = __toESM(require("@mui/material/Snackbar"));
4072
4107
  import_Alert6 = __toESM(require("@mui/material/Alert"));
@@ -4096,8 +4131,8 @@ var init_LiteLLMPage = __esm({
4096
4131
  isPageTab = (v) => !!v && PAGE_TABS.includes(v);
4097
4132
  LiteLLMPage = () => {
4098
4133
  const api = (0, import_core_plugin_api4.useApi)(liteLlmApiRef);
4099
- const [dateRange, setDateRange] = (0, import_react12.useState)(initDateRange);
4100
- const [currentPreset, setCurrentPreset] = (0, import_react12.useState)(() => {
4134
+ const [dateRange, setDateRange] = (0, import_react13.useState)(initDateRange);
4135
+ const [currentPreset, setCurrentPreset] = (0, import_react13.useState)(() => {
4101
4136
  try {
4102
4137
  return localStorage.getItem(PERIOD_LS_KEY2) ?? "7d";
4103
4138
  } catch {
@@ -4105,14 +4140,14 @@ var init_LiteLLMPage = __esm({
4105
4140
  }
4106
4141
  });
4107
4142
  const [searchParams, setSearchParams] = (0, import_react_router_dom.useSearchParams)();
4108
- const [activeTab, setActiveTab] = (0, import_react12.useState)(() => {
4143
+ const [activeTab, setActiveTab] = (0, import_react13.useState)(() => {
4109
4144
  const t = searchParams.get("tab");
4110
4145
  return isPageTab(t) ? t : "overview";
4111
4146
  });
4112
- const [generateDialogOpen, setGenerateDialogOpen] = (0, import_react12.useState)(
4147
+ const [generateDialogOpen, setGenerateDialogOpen] = (0, import_react13.useState)(
4113
4148
  () => searchParams.get("generate") === "1"
4114
4149
  );
4115
- (0, import_react12.useEffect)(() => {
4150
+ (0, import_react13.useEffect)(() => {
4116
4151
  if (searchParams.get("generate") !== "1") return;
4117
4152
  setGenerateDialogOpen(true);
4118
4153
  setSearchParams(
@@ -4124,7 +4159,7 @@ var init_LiteLLMPage = __esm({
4124
4159
  { replace: true }
4125
4160
  );
4126
4161
  }, [searchParams, setSearchParams]);
4127
- const selectTab = (0, import_react12.useCallback)(
4162
+ const selectTab = (0, import_react13.useCallback)(
4128
4163
  (tab) => {
4129
4164
  setActiveTab(tab);
4130
4165
  setSearchParams(
@@ -4138,12 +4173,12 @@ var init_LiteLLMPage = __esm({
4138
4173
  },
4139
4174
  [setSearchParams]
4140
4175
  );
4141
- const [snackbar, setSnackbar] = (0, import_react12.useState)(null);
4142
- const [manageTeam, setManageTeam] = (0, import_react12.useState)(null);
4143
- const [keyToEdit, setKeyToEdit] = (0, import_react12.useState)(null);
4176
+ const [snackbar, setSnackbar] = (0, import_react13.useState)(null);
4177
+ const [manageTeam, setManageTeam] = (0, import_react13.useState)(null);
4178
+ const [keyToEdit, setKeyToEdit] = (0, import_react13.useState)(null);
4144
4179
  const keyFormOpen = generateDialogOpen || !!keyToEdit;
4145
- const [teamUsageCache, setTeamUsageCache] = (0, import_react12.useState)({});
4146
- const [teamUsageLoading, setTeamUsageLoading] = (0, import_react12.useState)({});
4180
+ const [teamUsageCache, setTeamUsageCache] = (0, import_react13.useState)({});
4181
+ const [teamUsageLoading, setTeamUsageLoading] = (0, import_react13.useState)({});
4147
4182
  const { value: userInfo, loading: userLoading, error: userError } = (0, import_react_use3.useAsync)(
4148
4183
  () => api.getUserInfo(),
4149
4184
  [api]
@@ -4187,7 +4222,7 @@ var init_LiteLLMPage = __esm({
4187
4222
  async () => objectPermsEnabled ? api.getMcpServers().catch(() => []) : [],
4188
4223
  [api, objectPermsEnabled]
4189
4224
  );
4190
- const teams = (0, import_react12.useMemo)(() => {
4225
+ const teams = (0, import_react13.useMemo)(() => {
4191
4226
  if (!allTeams?.length) return [];
4192
4227
  if (!userInfo) return allTeams;
4193
4228
  const userId = userInfo.user_id;
@@ -4204,7 +4239,7 @@ var init_LiteLLMPage = __esm({
4204
4239
  const endDate = dateRange.end.toISOString().split("T")[0];
4205
4240
  return api.getUsage(startDate, endDate);
4206
4241
  }, [api, dateRange]);
4207
- const handleDateRangeChange = (0, import_react12.useCallback)((range, preset) => {
4242
+ const handleDateRangeChange = (0, import_react13.useCallback)((range, preset) => {
4208
4243
  setDateRange(range);
4209
4244
  if (preset) {
4210
4245
  setCurrentPreset(preset);
@@ -4212,7 +4247,7 @@ var init_LiteLLMPage = __esm({
4212
4247
  setTeamUsageCache({});
4213
4248
  setTeamUsageLoading({});
4214
4249
  }, [setDateRange, setCurrentPreset]);
4215
- const loadTeamUsage = (0, import_react12.useCallback)(async (teamId) => {
4250
+ const loadTeamUsage = (0, import_react13.useCallback)(async (teamId) => {
4216
4251
  if (teamUsageCache[teamId] !== void 0 || teamUsageLoading[teamId]) return;
4217
4252
  setTeamUsageLoading((prev) => ({ ...prev, [teamId]: true }));
4218
4253
  try {
@@ -4226,7 +4261,7 @@ var init_LiteLLMPage = __esm({
4226
4261
  setTeamUsageLoading((prev) => ({ ...prev, [teamId]: false }));
4227
4262
  }
4228
4263
  }, [api, dateRange, teamUsageCache, teamUsageLoading]);
4229
- const allowedModels = (0, import_react12.useMemo)(() => {
4264
+ const allowedModels = (0, import_react13.useMemo)(() => {
4230
4265
  if (!allModels?.length) return [];
4231
4266
  const userModels = userInfo?.models;
4232
4267
  const teamModels = teams?.flatMap((t) => t.models ?? []);
@@ -4239,7 +4274,7 @@ var init_LiteLLMPage = __esm({
4239
4274
  ]);
4240
4275
  return allModels.filter((m) => allowed.has(m.model_name));
4241
4276
  }, [allModels, userInfo, teams]);
4242
- const handleGenerateKey = (0, import_react12.useCallback)(
4277
+ const handleGenerateKey = (0, import_react13.useCallback)(
4243
4278
  async (request) => {
4244
4279
  try {
4245
4280
  const response = await api.generateKey(request);
@@ -4253,7 +4288,7 @@ var init_LiteLLMPage = __esm({
4253
4288
  },
4254
4289
  [api, refreshKeys]
4255
4290
  );
4256
- const handleUpdateKey = (0, import_react12.useCallback)(
4291
+ const handleUpdateKey = (0, import_react13.useCallback)(
4257
4292
  async (keyId, request) => {
4258
4293
  try {
4259
4294
  await api.updateKey(keyId, request);
@@ -4266,7 +4301,7 @@ var init_LiteLLMPage = __esm({
4266
4301
  },
4267
4302
  [api, refreshKeys]
4268
4303
  );
4269
- const handleBlockKey = (0, import_react12.useCallback)(
4304
+ const handleBlockKey = (0, import_react13.useCallback)(
4270
4305
  async (keyId) => {
4271
4306
  try {
4272
4307
  await api.blockKey(keyId);
@@ -4278,7 +4313,7 @@ var init_LiteLLMPage = __esm({
4278
4313
  },
4279
4314
  [api, refreshKeys]
4280
4315
  );
4281
- const handleUnblockKey = (0, import_react12.useCallback)(
4316
+ const handleUnblockKey = (0, import_react13.useCallback)(
4282
4317
  async (keyId) => {
4283
4318
  try {
4284
4319
  await api.unblockKey(keyId);
@@ -4290,7 +4325,7 @@ var init_LiteLLMPage = __esm({
4290
4325
  },
4291
4326
  [api, refreshKeys]
4292
4327
  );
4293
- const handleResetKeySpend = (0, import_react12.useCallback)(
4328
+ const handleResetKeySpend = (0, import_react13.useCallback)(
4294
4329
  async (keyId) => {
4295
4330
  try {
4296
4331
  await api.resetKeySpend(keyId);
@@ -4302,7 +4337,7 @@ var init_LiteLLMPage = __esm({
4302
4337
  },
4303
4338
  [api, refreshKeys]
4304
4339
  );
4305
- const handleDeleteKey = (0, import_react12.useCallback)(
4340
+ const handleDeleteKey = (0, import_react13.useCallback)(
4306
4341
  async (keyId) => {
4307
4342
  try {
4308
4343
  await api.deleteKey(keyId);
@@ -4319,7 +4354,7 @@ var init_LiteLLMPage = __esm({
4319
4354
  },
4320
4355
  [api, refreshKeys]
4321
4356
  );
4322
- const handlePruneExpiredKeys = (0, import_react12.useCallback)(
4357
+ const handlePruneExpiredKeys = (0, import_react13.useCallback)(
4323
4358
  async () => {
4324
4359
  try {
4325
4360
  const result = await api.pruneExpiredKeys();
@@ -4334,14 +4369,14 @@ var init_LiteLLMPage = __esm({
4334
4369
  );
4335
4370
  const isInitialLoading = userLoading && !userInfo;
4336
4371
  if (isInitialLoading) {
4337
- return /* @__PURE__ */ import_react12.default.createElement(import_Box12.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "50vh" }, /* @__PURE__ */ import_react12.default.createElement(import_CircularProgress6.default, null));
4372
+ return /* @__PURE__ */ import_react13.default.createElement(import_Box12.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "50vh" }, /* @__PURE__ */ import_react13.default.createElement(import_CircularProgress6.default, null));
4338
4373
  }
4339
4374
  if (userError || !userInfo) {
4340
4375
  const isProvisioningEnabled = userError?.body?.provisioning === true;
4341
4376
  const hint = userError?.body?.hint;
4342
- return /* @__PURE__ */ import_react12.default.createElement(import_Box12.default, { p: 3 }, /* @__PURE__ */ import_react12.default.createElement(import_Paper8.default, { sx: { p: 3 } }, /* @__PURE__ */ import_react12.default.createElement(import_Typography12.default, { variant: "h6", gutterBottom: true }, "Account not provisioned"), /* @__PURE__ */ import_react12.default.createElement(import_Typography12.default, { color: "text.secondary", paragraph: true }, "Your Backstage account is not linked to a LiteLLM user."), hint ? /* @__PURE__ */ import_react12.default.createElement(import_Typography12.default, { variant: "body2", color: "text.secondary" }, hint) : /* @__PURE__ */ import_react12.default.createElement(import_Typography12.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.")));
4377
+ return /* @__PURE__ */ import_react13.default.createElement(import_Box12.default, { p: 3 }, /* @__PURE__ */ import_react13.default.createElement(import_Paper8.default, { sx: { p: 3 } }, /* @__PURE__ */ import_react13.default.createElement(import_Typography12.default, { variant: "h6", gutterBottom: true }, "Account not provisioned"), /* @__PURE__ */ import_react13.default.createElement(import_Typography12.default, { color: "text.secondary", paragraph: true }, "Your Backstage account is not linked to a LiteLLM user."), hint ? /* @__PURE__ */ import_react13.default.createElement(import_Typography12.default, { variant: "body2", color: "text.secondary" }, hint) : /* @__PURE__ */ import_react13.default.createElement(import_Typography12.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.")));
4343
4378
  }
4344
- const pageTabs = /* @__PURE__ */ import_react12.default.createElement(
4379
+ const pageTabs = /* @__PURE__ */ import_react13.default.createElement(
4345
4380
  import_Tabs2.default,
4346
4381
  {
4347
4382
  value: activeTab,
@@ -4354,13 +4389,13 @@ var init_LiteLLMPage = __esm({
4354
4389
  '& [class*="MuiTab-root"]': { minHeight: 44, textTransform: "none", fontSize: 14 }
4355
4390
  }
4356
4391
  },
4357
- /* @__PURE__ */ import_react12.default.createElement(import_Tab2.default, { label: "Overview", value: "overview" }),
4358
- /* @__PURE__ */ import_react12.default.createElement(import_Tab2.default, { label: "Keys", value: "keys" }),
4359
- /* @__PURE__ */ import_react12.default.createElement(import_Tab2.default, { label: "Teams", value: "teams" }),
4360
- /* @__PURE__ */ import_react12.default.createElement(import_Tab2.default, { label: "Models", value: "models" }),
4361
- userInfo.can_view_audit && /* @__PURE__ */ import_react12.default.createElement(import_Tab2.default, { label: "Audit Log", value: "audit" })
4392
+ /* @__PURE__ */ import_react13.default.createElement(import_Tab2.default, { label: "Overview", value: "overview" }),
4393
+ /* @__PURE__ */ import_react13.default.createElement(import_Tab2.default, { label: "Keys", value: "keys" }),
4394
+ /* @__PURE__ */ import_react13.default.createElement(import_Tab2.default, { label: "Teams", value: "teams" }),
4395
+ /* @__PURE__ */ import_react13.default.createElement(import_Tab2.default, { label: "Models", value: "models" }),
4396
+ userInfo.can_view_audit && /* @__PURE__ */ import_react13.default.createElement(import_Tab2.default, { label: "Audit Log", value: "audit" })
4362
4397
  );
4363
- return /* @__PURE__ */ import_react12.default.createElement(import_Box12.default, { sx: { p: 3, display: "flex", flexDirection: "column", gap: 2 } }, /* @__PURE__ */ import_react12.default.createElement(
4398
+ return /* @__PURE__ */ import_react13.default.createElement(import_Box12.default, { sx: { p: 3, display: "flex", flexDirection: "column", gap: 2 } }, /* @__PURE__ */ import_react13.default.createElement(
4364
4399
  DashboardHeader,
4365
4400
  {
4366
4401
  userInfo,
@@ -4370,7 +4405,7 @@ var init_LiteLLMPage = __esm({
4370
4405
  onGenerateKeyClick: () => setGenerateDialogOpen(true),
4371
4406
  tabs: pageTabs
4372
4407
  }
4373
- ), activeTab === "overview" && /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { container: true, spacing: 2, alignItems: "flex-start" }, /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 12, lg: 8 }, /* @__PURE__ */ import_react12.default.createElement(
4408
+ ), activeTab === "overview" && /* @__PURE__ */ import_react13.default.createElement(import_Grid2.default, { container: true, spacing: 2, alignItems: "flex-start" }, /* @__PURE__ */ import_react13.default.createElement(import_Grid2.default, { item: true, xs: 12, lg: 8 }, /* @__PURE__ */ import_react13.default.createElement(
4374
4409
  UsageStats,
4375
4410
  {
4376
4411
  usage: usage ?? null,
@@ -4381,7 +4416,7 @@ var init_LiteLLMPage = __esm({
4381
4416
  loading: usageLoading,
4382
4417
  userInfo
4383
4418
  }
4384
- )), /* @__PURE__ */ import_react12.default.createElement(import_Grid2.default, { item: true, xs: 12, lg: 4 }, /* @__PURE__ */ import_react12.default.createElement(LiteLLMBudgetWidget, { compact: true, collapsible: true }))), activeTab === "keys" && /* @__PURE__ */ import_react12.default.createElement(
4419
+ )), /* @__PURE__ */ import_react13.default.createElement(import_Grid2.default, { item: true, xs: 12, lg: 4 }, /* @__PURE__ */ import_react13.default.createElement(LiteLLMBudgetWidget, { compact: true, collapsible: true }))), activeTab === "keys" && /* @__PURE__ */ import_react13.default.createElement(
4385
4420
  KeysTable,
4386
4421
  {
4387
4422
  keys: keys ?? [],
@@ -4398,7 +4433,7 @@ var init_LiteLLMPage = __esm({
4398
4433
  for (const t of managedTeams ?? []) teamsById.set(t.team_id, t);
4399
4434
  for (const t of teams ?? []) teamsById.set(t.team_id, t);
4400
4435
  const visibleTeams = Array.from(teamsById.values());
4401
- return /* @__PURE__ */ import_react12.default.createElement(
4436
+ return /* @__PURE__ */ import_react13.default.createElement(
4402
4437
  TeamUsage,
4403
4438
  {
4404
4439
  teams: visibleTeams,
@@ -4414,14 +4449,14 @@ var init_LiteLLMPage = __esm({
4414
4449
  onCreateTeam: () => setManageTeam({ mode: "create" })
4415
4450
  }
4416
4451
  );
4417
- })(), activeTab === "models" && /* @__PURE__ */ import_react12.default.createElement(
4452
+ })(), activeTab === "models" && /* @__PURE__ */ import_react13.default.createElement(
4418
4453
  ModelsTable,
4419
4454
  {
4420
4455
  allModels: allModels ?? [],
4421
4456
  teams: teams ?? [],
4422
4457
  loading: modelsLoading
4423
4458
  }
4424
- ), activeTab === "audit" && userInfo.can_view_audit && /* @__PURE__ */ import_react12.default.createElement(AuditLog, { api }), /* @__PURE__ */ import_react12.default.createElement(
4459
+ ), activeTab === "audit" && userInfo.can_view_audit && /* @__PURE__ */ import_react13.default.createElement(AuditLog, { api }), /* @__PURE__ */ import_react13.default.createElement(
4425
4460
  KeyFormDialog,
4426
4461
  {
4427
4462
  open: keyFormOpen,
@@ -4441,7 +4476,7 @@ var init_LiteLLMPage = __esm({
4441
4476
  onResetKeySpend: handleResetKeySpend,
4442
4477
  onGetConfig: () => api.getConfig()
4443
4478
  }
4444
- ), /* @__PURE__ */ import_react12.default.createElement(
4479
+ ), /* @__PURE__ */ import_react13.default.createElement(
4445
4480
  ManageTeamDialog,
4446
4481
  {
4447
4482
  open: !!manageTeam,
@@ -4503,7 +4538,7 @@ var init_LiteLLMPage = __esm({
4503
4538
  refreshTeams();
4504
4539
  }
4505
4540
  }
4506
- ), /* @__PURE__ */ import_react12.default.createElement(
4541
+ ), /* @__PURE__ */ import_react13.default.createElement(
4507
4542
  import_Snackbar2.default,
4508
4543
  {
4509
4544
  open: !!snackbar,
@@ -4511,7 +4546,7 @@ var init_LiteLLMPage = __esm({
4511
4546
  onClose: () => setSnackbar(null),
4512
4547
  anchorOrigin: { vertical: "bottom", horizontal: "right" }
4513
4548
  },
4514
- snackbar ? /* @__PURE__ */ import_react12.default.createElement(import_Alert6.default, { severity: snackbar.severity, onClose: () => setSnackbar(null) }, snackbar.message) : void 0
4549
+ snackbar ? /* @__PURE__ */ import_react13.default.createElement(import_Alert6.default, { severity: snackbar.severity, onClose: () => setSnackbar(null) }, snackbar.message) : void 0
4515
4550
  ));
4516
4551
  };
4517
4552
  }
@@ -4521,6 +4556,7 @@ var init_LiteLLMPage = __esm({
4521
4556
  var index_exports = {};
4522
4557
  __export(index_exports, {
4523
4558
  DashboardHeader: () => DashboardHeader,
4559
+ GenerateKeyButton: () => GenerateKeyButton,
4524
4560
  GenerateKeyDialog: () => GenerateKeyDialog,
4525
4561
  KeyFormDialog: () => KeyFormDialog,
4526
4562
  KeysTable: () => KeysTable,
@@ -4543,7 +4579,7 @@ __export(index_exports, {
4543
4579
  module.exports = __toCommonJS(index_exports);
4544
4580
 
4545
4581
  // src/plugin.tsx
4546
- var import_react13 = __toESM(require("react"));
4582
+ var import_react14 = __toESM(require("react"));
4547
4583
  var import_icons_material9 = require("@mui/icons-material");
4548
4584
  var import_frontend_plugin_api = require("@backstage/frontend-plugin-api");
4549
4585
  init_api();
@@ -4558,10 +4594,10 @@ var liteLlmPage = import_frontend_plugin_api.PageBlueprint.make({
4558
4594
  params: {
4559
4595
  path: "/litellm",
4560
4596
  title: "LiteLLM",
4561
- icon: /* @__PURE__ */ import_react13.default.createElement(import_icons_material9.TrendingUp, null),
4597
+ icon: /* @__PURE__ */ import_react14.default.createElement(import_icons_material9.TrendingUp, null),
4562
4598
  loader: async () => {
4563
4599
  const { LiteLLMPage: LiteLLMPage2 } = await Promise.resolve().then(() => (init_LiteLLMPage(), LiteLLMPage_exports));
4564
- return /* @__PURE__ */ import_react13.default.createElement(LiteLLMPage2, null);
4600
+ return /* @__PURE__ */ import_react14.default.createElement(LiteLLMPage2, null);
4565
4601
  }
4566
4602
  }
4567
4603
  });
@@ -4578,7 +4614,7 @@ init_UsageStats();
4578
4614
  init_TeamUsage();
4579
4615
 
4580
4616
  // src/components/LiteLLMHomeWidget.tsx
4581
- var import_react14 = __toESM(require("react"));
4617
+ var import_react15 = __toESM(require("react"));
4582
4618
  var import_Paper9 = __toESM(require("@mui/material/Paper"));
4583
4619
  var import_Box13 = __toESM(require("@mui/material/Box"));
4584
4620
  var import_Typography13 = __toESM(require("@mui/material/Typography"));
@@ -4604,19 +4640,19 @@ function presetToDateRange(preset) {
4604
4640
  }
4605
4641
  return { start, end };
4606
4642
  }
4607
- var Kpi = ({ label, value }) => /* @__PURE__ */ import_react14.default.createElement(import_Box13.default, null, /* @__PURE__ */ import_react14.default.createElement(import_Typography13.default, { variant: "caption", color: "text.secondary", display: "block" }, label), /* @__PURE__ */ import_react14.default.createElement(import_Typography13.default, { variant: "subtitle1", fontWeight: 600 }, value));
4643
+ var Kpi = ({ label, value }) => /* @__PURE__ */ import_react15.default.createElement(import_Box13.default, null, /* @__PURE__ */ import_react15.default.createElement(import_Typography13.default, { variant: "caption", color: "text.secondary", display: "block" }, label), /* @__PURE__ */ import_react15.default.createElement(import_Typography13.default, { variant: "subtitle1", fontWeight: 600 }, value));
4608
4644
  var LiteLLMHomeWidget = ({
4609
4645
  defaultPeriod = "7d",
4610
4646
  title = "LiteLLM Usage"
4611
4647
  }) => {
4612
4648
  const api = (0, import_core_plugin_api5.useApi)(liteLlmApiRef);
4613
- const [period, setPeriod] = (0, import_react14.useState)(defaultPeriod);
4614
- const [loading, setLoading] = (0, import_react14.useState)(true);
4615
- const [usageError, setUsageError] = (0, import_react14.useState)(null);
4616
- const [keysError, setKeysError] = (0, import_react14.useState)(null);
4617
- const [usage, setUsage] = (0, import_react14.useState)(null);
4618
- const [keys, setKeys] = (0, import_react14.useState)([]);
4619
- (0, import_react14.useEffect)(() => {
4649
+ const [period, setPeriod] = (0, import_react15.useState)(defaultPeriod);
4650
+ const [loading, setLoading] = (0, import_react15.useState)(true);
4651
+ const [usageError, setUsageError] = (0, import_react15.useState)(null);
4652
+ const [keysError, setKeysError] = (0, import_react15.useState)(null);
4653
+ const [usage, setUsage] = (0, import_react15.useState)(null);
4654
+ const [keys, setKeys] = (0, import_react15.useState)([]);
4655
+ (0, import_react15.useEffect)(() => {
4620
4656
  let cancelled = false;
4621
4657
  setLoading(true);
4622
4658
  setUsageError(null);
@@ -4653,17 +4689,17 @@ var LiteLLMHomeWidget = ({
4653
4689
  spend: d.spend
4654
4690
  }));
4655
4691
  const hasSparkline = dailyData.length > 0;
4656
- return /* @__PURE__ */ import_react14.default.createElement(import_Paper9.default, { sx: { p: 2 } }, /* @__PURE__ */ import_react14.default.createElement(import_Box13.default, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1.5 }, /* @__PURE__ */ import_react14.default.createElement(import_Typography13.default, { variant: "h6" }, title), /* @__PURE__ */ import_react14.default.createElement(import_FormControl2.default, { size: "small", sx: { minWidth: 90 } }, /* @__PURE__ */ import_react14.default.createElement(
4692
+ return /* @__PURE__ */ import_react15.default.createElement(import_Paper9.default, { sx: { p: 2 } }, /* @__PURE__ */ import_react15.default.createElement(import_Box13.default, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 1.5 }, /* @__PURE__ */ import_react15.default.createElement(import_Typography13.default, { variant: "h6" }, title), /* @__PURE__ */ import_react15.default.createElement(import_FormControl2.default, { size: "small", sx: { minWidth: 90 } }, /* @__PURE__ */ import_react15.default.createElement(
4657
4693
  import_Select2.default,
4658
4694
  {
4659
4695
  value: period,
4660
4696
  onChange: (e) => setPeriod(e.target.value),
4661
4697
  displayEmpty: true
4662
4698
  },
4663
- /* @__PURE__ */ import_react14.default.createElement(import_MenuItem6.default, { value: "today" }, "Today"),
4664
- /* @__PURE__ */ import_react14.default.createElement(import_MenuItem6.default, { value: "7d" }, "7d"),
4665
- /* @__PURE__ */ import_react14.default.createElement(import_MenuItem6.default, { value: "30d" }, "30d")
4666
- ))), loading && /* @__PURE__ */ import_react14.default.createElement(import_Box13.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 120 }, /* @__PURE__ */ import_react14.default.createElement(import_CircularProgress7.default, { size: 32 })), !loading && totalFailure && /* @__PURE__ */ import_react14.default.createElement(import_Alert7.default, { severity: "error", sx: { mt: 1 } }, usageError ?? "Failed to load usage data"), !loading && !totalFailure && /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, partialFailure && /* @__PURE__ */ import_react14.default.createElement(import_Alert7.default, { severity: "warning", sx: { mt: 1, mb: 1 } }, usageError ? `Usage data unavailable (${usageError}).` : "", keysError ? ` Key list unavailable (${keysError}).` : "", " Showing what loaded."), /* @__PURE__ */ import_react14.default.createElement(import_Grid3.default, { container: true, spacing: 2, sx: { mb: hasSparkline ? 1.5 : 0 } }, /* @__PURE__ */ import_react14.default.createElement(import_Grid3.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react14.default.createElement(Kpi, { label: "USD Spent", value: fmtUsd(usage?.total_spend ?? 0) })), /* @__PURE__ */ import_react14.default.createElement(import_Grid3.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react14.default.createElement(Kpi, { label: "Tokens In", value: fmtInt(usage?.prompt_tokens ?? 0) })), /* @__PURE__ */ import_react14.default.createElement(import_Grid3.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react14.default.createElement(Kpi, { label: "Tokens Out", value: fmtInt(usage?.completion_tokens ?? 0) })), /* @__PURE__ */ import_react14.default.createElement(import_Grid3.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react14.default.createElement(Kpi, { label: "Keys", value: fmtInt(keys.length) }))), hasSparkline && /* @__PURE__ */ import_react14.default.createElement(import_Box13.default, { height: 120 }, /* @__PURE__ */ import_react14.default.createElement(import_recharts3.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react14.default.createElement(import_recharts3.AreaChart, { data: dailyData, margin: { top: 4, right: 0, bottom: 0, left: 0 } }, /* @__PURE__ */ import_react14.default.createElement(
4699
+ /* @__PURE__ */ import_react15.default.createElement(import_MenuItem6.default, { value: "today" }, "Today"),
4700
+ /* @__PURE__ */ import_react15.default.createElement(import_MenuItem6.default, { value: "7d" }, "7d"),
4701
+ /* @__PURE__ */ import_react15.default.createElement(import_MenuItem6.default, { value: "30d" }, "30d")
4702
+ ))), loading && /* @__PURE__ */ import_react15.default.createElement(import_Box13.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 120 }, /* @__PURE__ */ import_react15.default.createElement(import_CircularProgress7.default, { size: 32 })), !loading && totalFailure && /* @__PURE__ */ import_react15.default.createElement(import_Alert7.default, { severity: "error", sx: { mt: 1 } }, usageError ?? "Failed to load usage data"), !loading && !totalFailure && /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, partialFailure && /* @__PURE__ */ import_react15.default.createElement(import_Alert7.default, { severity: "warning", sx: { mt: 1, mb: 1 } }, usageError ? `Usage data unavailable (${usageError}).` : "", keysError ? ` Key list unavailable (${keysError}).` : "", " Showing what loaded."), /* @__PURE__ */ import_react15.default.createElement(import_Grid3.default, { container: true, spacing: 2, sx: { mb: hasSparkline ? 1.5 : 0 } }, /* @__PURE__ */ import_react15.default.createElement(import_Grid3.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react15.default.createElement(Kpi, { label: "USD Spent", value: fmtUsd(usage?.total_spend ?? 0) })), /* @__PURE__ */ import_react15.default.createElement(import_Grid3.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react15.default.createElement(Kpi, { label: "Tokens In", value: fmtInt(usage?.prompt_tokens ?? 0) })), /* @__PURE__ */ import_react15.default.createElement(import_Grid3.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react15.default.createElement(Kpi, { label: "Tokens Out", value: fmtInt(usage?.completion_tokens ?? 0) })), /* @__PURE__ */ import_react15.default.createElement(import_Grid3.default, { item: true, xs: 6 }, /* @__PURE__ */ import_react15.default.createElement(Kpi, { label: "Keys", value: fmtInt(keys.length) }))), hasSparkline && /* @__PURE__ */ import_react15.default.createElement(import_Box13.default, { height: 120 }, /* @__PURE__ */ import_react15.default.createElement(import_recharts3.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react15.default.createElement(import_recharts3.AreaChart, { data: dailyData, margin: { top: 4, right: 0, bottom: 0, left: 0 } }, /* @__PURE__ */ import_react15.default.createElement(
4667
4703
  import_recharts3.Area,
4668
4704
  {
4669
4705
  type: "monotone",
@@ -4681,7 +4717,7 @@ var LiteLLMHomeWidget = ({
4681
4717
  init_LiteLLMBudgetWidget();
4682
4718
 
4683
4719
  // src/components/LiteLLMBudgetGauges.tsx
4684
- var import_react15 = __toESM(require("react"));
4720
+ var import_react16 = __toESM(require("react"));
4685
4721
  var import_Paper10 = __toESM(require("@mui/material/Paper"));
4686
4722
  var import_Box14 = __toESM(require("@mui/material/Box"));
4687
4723
  var import_Button6 = __toESM(require("@mui/material/Button"));
@@ -4690,11 +4726,13 @@ var import_CircularProgress8 = __toESM(require("@mui/material/CircularProgress")
4690
4726
  var import_Alert8 = __toESM(require("@mui/material/Alert"));
4691
4727
  var import_Collapse4 = __toESM(require("@mui/material/Collapse"));
4692
4728
  var import_icons_material10 = require("@mui/icons-material");
4729
+ var import_recharts4 = require("recharts");
4693
4730
  var import_core_plugin_api6 = require("@backstage/core-plugin-api");
4694
- var import_core_components2 = require("@backstage/core-components");
4731
+ var import_core_components3 = require("@backstage/core-components");
4695
4732
  init_api();
4696
4733
  init_format();
4697
4734
  init_ui();
4735
+ init_GenerateKeyButton();
4698
4736
  init_BudgetLimitList();
4699
4737
  init_budget();
4700
4738
  var MODULE_PATH = "/litellm";
@@ -4705,7 +4743,7 @@ var LEVEL = {
4705
4743
  };
4706
4744
  var DEFAULT_CTAS = ["new-key", "module", "all-limits"];
4707
4745
  var CTA_LABELS = {
4708
- "new-key": "New key",
4746
+ "new-key": "Generate New Key",
4709
4747
  module: "Open module",
4710
4748
  "all-limits": "All limits"
4711
4749
  };
@@ -4731,7 +4769,7 @@ var LevelGauge = ({
4731
4769
  const limit = gauge.limit;
4732
4770
  const tone = limit ? budgetTone2(limit.pct) : "neutral";
4733
4771
  const extra = gauge.kind === "key" ? Math.max(0, gauge.count - 1) : 0;
4734
- return /* @__PURE__ */ import_react15.default.createElement(
4772
+ return /* @__PURE__ */ import_react16.default.createElement(
4735
4773
  import_Box14.default,
4736
4774
  {
4737
4775
  sx: {
@@ -4742,7 +4780,7 @@ var LevelGauge = ({
4742
4780
  flex: 1
4743
4781
  }
4744
4782
  },
4745
- /* @__PURE__ */ import_react15.default.createElement(
4783
+ /* @__PURE__ */ import_react16.default.createElement(
4746
4784
  Gauge,
4747
4785
  {
4748
4786
  value: limit?.pct ?? 0,
@@ -4751,7 +4789,7 @@ var LevelGauge = ({
4751
4789
  label: limit ? `${Math.round(limit.pct)}%` : "\u2014"
4752
4790
  }
4753
4791
  ),
4754
- /* @__PURE__ */ import_react15.default.createElement(
4792
+ /* @__PURE__ */ import_react16.default.createElement(
4755
4793
  import_Typography14.default,
4756
4794
  {
4757
4795
  sx: (theme) => ({
@@ -4765,7 +4803,7 @@ var LevelGauge = ({
4765
4803
  },
4766
4804
  name
4767
4805
  ),
4768
- limit ? /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement(
4806
+ limit ? /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(
4769
4807
  import_Typography14.default,
4770
4808
  {
4771
4809
  variant: "caption",
@@ -4781,7 +4819,7 @@ var LevelGauge = ({
4781
4819
  }
4782
4820
  },
4783
4821
  limit.label
4784
- ), /* @__PURE__ */ import_react15.default.createElement(
4822
+ ), /* @__PURE__ */ import_react16.default.createElement(
4785
4823
  import_Typography14.default,
4786
4824
  {
4787
4825
  variant: "caption",
@@ -4793,10 +4831,10 @@ var LevelGauge = ({
4793
4831
  }
4794
4832
  },
4795
4833
  spendCaption(limit)
4796
- ), extra > 0 ? /* @__PURE__ */ import_react15.default.createElement(
4834
+ ), extra > 0 ? /* @__PURE__ */ import_react16.default.createElement(
4797
4835
  import_Typography14.default,
4798
4836
  {
4799
- component: import_core_components2.Link,
4837
+ component: import_core_components3.Link,
4800
4838
  to: keysHref,
4801
4839
  variant: "caption",
4802
4840
  sx: {
@@ -4809,7 +4847,7 @@ var LevelGauge = ({
4809
4847
  "+",
4810
4848
  extra,
4811
4849
  " more"
4812
- ) : /* @__PURE__ */ import_react15.default.createElement(import_Typography14.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 10.5 } }, resetLabel(limit))) : /* @__PURE__ */ import_react15.default.createElement(
4850
+ ) : /* @__PURE__ */ import_react16.default.createElement(import_Typography14.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 10.5 } }, resetLabel(limit))) : /* @__PURE__ */ import_react16.default.createElement(
4813
4851
  import_Typography14.default,
4814
4852
  {
4815
4853
  variant: "caption",
@@ -4820,6 +4858,125 @@ var LevelGauge = ({
4820
4858
  )
4821
4859
  );
4822
4860
  };
4861
+ function monthToDateRange(now = /* @__PURE__ */ new Date()) {
4862
+ const toDay = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(
4863
+ d.getDate()
4864
+ ).padStart(2, "0")}`;
4865
+ const start = new Date(now.getFullYear(), now.getMonth(), 1);
4866
+ return { startDate: toDay(start), endDate: toDay(now) };
4867
+ }
4868
+ var UsageMiniChart = ({ data, totalTokens, loading, height }) => {
4869
+ const renderPlot = () => {
4870
+ if (loading) {
4871
+ return /* @__PURE__ */ import_react16.default.createElement(import_Box14.default, { display: "flex", justifyContent: "center", alignItems: "center", height: "100%" }, /* @__PURE__ */ import_react16.default.createElement(import_CircularProgress8.default, { size: 20 }));
4872
+ }
4873
+ if (data.length === 0) {
4874
+ return /* @__PURE__ */ import_react16.default.createElement(
4875
+ import_Box14.default,
4876
+ {
4877
+ display: "flex",
4878
+ justifyContent: "center",
4879
+ alignItems: "center",
4880
+ height: "100%",
4881
+ sx: (theme) => ({ color: theme.palette.text.secondary, fontSize: 18 })
4882
+ },
4883
+ "\u2014"
4884
+ );
4885
+ }
4886
+ return /* @__PURE__ */ import_react16.default.createElement(import_recharts4.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react16.default.createElement(import_recharts4.AreaChart, { data, margin: { top: 4, right: 0, bottom: 0, left: 0 } }, /* @__PURE__ */ import_react16.default.createElement(import_recharts4.Tooltip, { content: /* @__PURE__ */ import_react16.default.createElement(ChartTooltip, { valueFormatter: fmtInt }) }), /* @__PURE__ */ import_react16.default.createElement(
4887
+ import_recharts4.Area,
4888
+ {
4889
+ type: "monotone",
4890
+ dataKey: "input",
4891
+ name: "Input",
4892
+ stackId: "tok",
4893
+ stroke: SERIES.input,
4894
+ strokeWidth: 1.5,
4895
+ fill: SERIES.input,
4896
+ fillOpacity: 0.25,
4897
+ dot: false,
4898
+ isAnimationActive: false
4899
+ }
4900
+ ), /* @__PURE__ */ import_react16.default.createElement(
4901
+ import_recharts4.Area,
4902
+ {
4903
+ type: "monotone",
4904
+ dataKey: "output",
4905
+ name: "Output",
4906
+ stackId: "tok",
4907
+ stroke: SERIES.output,
4908
+ strokeWidth: 1.5,
4909
+ fill: SERIES.output,
4910
+ fillOpacity: 0.25,
4911
+ dot: false,
4912
+ isAnimationActive: false
4913
+ }
4914
+ )));
4915
+ };
4916
+ const renderCaption = () => {
4917
+ if (loading) {
4918
+ return /* @__PURE__ */ import_react16.default.createElement(import_Typography14.default, { variant: "caption", color: "text.secondary", sx: { mt: 0.25, fontSize: 11 } }, "\u2026");
4919
+ }
4920
+ if (data.length === 0) {
4921
+ return /* @__PURE__ */ import_react16.default.createElement(
4922
+ import_Typography14.default,
4923
+ {
4924
+ variant: "caption",
4925
+ color: "text.secondary",
4926
+ sx: { mt: 0.25, fontSize: 10.5, textAlign: "center" }
4927
+ },
4928
+ "No usage this month"
4929
+ );
4930
+ }
4931
+ return /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(
4932
+ import_Typography14.default,
4933
+ {
4934
+ variant: "caption",
4935
+ title: `${fmtInt(totalTokens)} tokens month to date`,
4936
+ sx: {
4937
+ mt: 0.25,
4938
+ fontSize: 11,
4939
+ fontWeight: 600,
4940
+ maxWidth: "100%",
4941
+ overflow: "hidden",
4942
+ textOverflow: "ellipsis",
4943
+ whiteSpace: "nowrap",
4944
+ fontVariantNumeric: "tabular-nums"
4945
+ }
4946
+ },
4947
+ fmtCompact(totalTokens),
4948
+ " tokens"
4949
+ ), /* @__PURE__ */ import_react16.default.createElement(import_Typography14.default, { variant: "caption", color: "text.secondary", sx: { fontSize: 10.5 } }, "month to date"));
4950
+ };
4951
+ return /* @__PURE__ */ import_react16.default.createElement(
4952
+ import_Box14.default,
4953
+ {
4954
+ sx: {
4955
+ display: "flex",
4956
+ flexDirection: "column",
4957
+ alignItems: "center",
4958
+ minWidth: 0,
4959
+ flex: 1
4960
+ }
4961
+ },
4962
+ /* @__PURE__ */ import_react16.default.createElement(import_Box14.default, { sx: { height, width: "100%" } }, renderPlot()),
4963
+ /* @__PURE__ */ import_react16.default.createElement(
4964
+ import_Typography14.default,
4965
+ {
4966
+ sx: (theme) => ({
4967
+ mt: 0.75,
4968
+ fontSize: 10.5,
4969
+ fontWeight: 700,
4970
+ letterSpacing: "0.08em",
4971
+ textTransform: "uppercase",
4972
+ color: theme.palette.text.secondary
4973
+ })
4974
+ },
4975
+ "Usage"
4976
+ ),
4977
+ renderCaption()
4978
+ );
4979
+ };
4823
4980
  var LiteLLMBudgetGauges = ({
4824
4981
  title = "Budget",
4825
4982
  size = 72,
@@ -4834,60 +4991,83 @@ var LiteLLMBudgetGauges = ({
4834
4991
  action
4835
4992
  }) => {
4836
4993
  const api = (0, import_core_plugin_api6.useApi)(liteLlmApiRef);
4837
- const [loading, setLoading] = (0, import_react15.useState)(true);
4838
- const [error, setError] = (0, import_react15.useState)(null);
4839
- const [user, setUser] = (0, import_react15.useState)(null);
4840
- const [teams, setTeams] = (0, import_react15.useState)([]);
4841
- const [keys, setKeys] = (0, import_react15.useState)([]);
4994
+ const [loading, setLoading] = (0, import_react16.useState)(true);
4995
+ const [error, setError] = (0, import_react16.useState)(null);
4996
+ const [user, setUser] = (0, import_react16.useState)(null);
4997
+ const [teams, setTeams] = (0, import_react16.useState)([]);
4998
+ const [keys, setKeys] = (0, import_react16.useState)([]);
4999
+ const [usageLoading, setUsageLoading] = (0, import_react16.useState)(true);
5000
+ const [dailyTokens, setDailyTokens] = (0, import_react16.useState)([]);
5001
+ const [mtdTokens, setMtdTokens] = (0, import_react16.useState)(0);
4842
5002
  const isControlled = expanded !== void 0;
4843
- const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react15.useState)(defaultExpanded);
5003
+ const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react16.useState)(defaultExpanded);
4844
5004
  const isExpanded = isControlled ? expanded : uncontrolledExpanded;
4845
- const toggleExpanded = (0, import_react15.useCallback)(() => {
5005
+ const toggleExpanded = (0, import_react16.useCallback)(() => {
4846
5006
  const next = !isExpanded;
4847
5007
  if (!isControlled) setUncontrolledExpanded(next);
4848
5008
  onExpandedChange?.(next);
4849
5009
  }, [isControlled, isExpanded, onExpandedChange]);
4850
5010
  const keysTabHref = keysHref ?? `${moduleHref}?tab=keys`;
4851
- (0, import_react15.useEffect)(() => {
5011
+ (0, import_react16.useEffect)(() => {
4852
5012
  let cancelled = false;
4853
5013
  setLoading(true);
5014
+ setUsageLoading(true);
4854
5015
  setError(null);
4855
- Promise.allSettled([api.getUserInfo(), api.getTeams(), api.listKeys()]).then(
4856
- ([userResult, teamsResult, keysResult]) => {
4857
- if (cancelled) return;
4858
- if (userResult.status === "fulfilled") {
4859
- setUser(userResult.value);
4860
- } else {
4861
- setUser(null);
4862
- setError(
4863
- userResult.reason?.message ?? "Failed to load your LiteLLM profile"
4864
- );
4865
- }
4866
- setTeams(teamsResult.status === "fulfilled" ? teamsResult.value : []);
4867
- setKeys(keysResult.status === "fulfilled" ? keysResult.value : []);
4868
- setLoading(false);
5016
+ const { startDate, endDate } = monthToDateRange();
5017
+ Promise.allSettled([
5018
+ api.getUserInfo(),
5019
+ api.getTeams(),
5020
+ api.listKeys(),
5021
+ api.getUsage(startDate, endDate)
5022
+ ]).then(([userResult, teamsResult, keysResult, usageResult]) => {
5023
+ if (cancelled) return;
5024
+ if (userResult.status === "fulfilled") {
5025
+ setUser(userResult.value);
5026
+ } else {
5027
+ setUser(null);
5028
+ setError(
5029
+ userResult.reason?.message ?? "Failed to load your LiteLLM profile"
5030
+ );
4869
5031
  }
4870
- );
5032
+ setTeams(teamsResult.status === "fulfilled" ? teamsResult.value : []);
5033
+ setKeys(keysResult.status === "fulfilled" ? keysResult.value : []);
5034
+ setLoading(false);
5035
+ if (usageResult.status === "fulfilled") {
5036
+ const daily = usageResult.value.daily_usage ?? [];
5037
+ setDailyTokens(
5038
+ daily.map((d) => ({
5039
+ date: d.date,
5040
+ input: d.prompt_tokens,
5041
+ output: d.completion_tokens
5042
+ }))
5043
+ );
5044
+ setMtdTokens(usageResult.value.total_tokens ?? 0);
5045
+ } else {
5046
+ setDailyTokens([]);
5047
+ setMtdTokens(0);
5048
+ }
5049
+ setUsageLoading(false);
5050
+ });
4871
5051
  return () => {
4872
5052
  cancelled = true;
4873
5053
  };
4874
5054
  }, [api]);
4875
- const summary = (0, import_react15.useMemo)(
5055
+ const summary = (0, import_react16.useMemo)(
4876
5056
  () => buildBudgetSummary(user, teams, keys, keys.length),
4877
5057
  [user, teams, keys]
4878
5058
  );
4879
- const gauges = (0, import_react15.useMemo)(() => buildBudgetGauges(summary), [summary]);
4880
- const headline = (0, import_react15.useMemo)(() => budgetHeadline(summary), [summary]);
4881
- const expandedSummary = (0, import_react15.useMemo)(
5059
+ const gauges = (0, import_react16.useMemo)(() => buildBudgetGauges(summary), [summary]);
5060
+ const headline = (0, import_react16.useMemo)(() => budgetHeadline(summary), [summary]);
5061
+ const expandedSummary = (0, import_react16.useMemo)(
4882
5062
  () => buildBudgetSummary(user, teams, keys, maxExpandedKeys),
4883
5063
  [user, teams, keys, maxExpandedKeys]
4884
5064
  );
4885
- const expandedLimits = (0, import_react15.useMemo)(
5065
+ const expandedLimits = (0, import_react16.useMemo)(
4886
5066
  () => allBudgetLimits(expandedSummary),
4887
5067
  [expandedSummary]
4888
5068
  );
4889
5069
  const summaryText = headline.count === 0 ? "no limits apply" : `${headline.count} limit${headline.count === 1 ? "" : "s"}`;
4890
- const resolvedCtas = (0, import_react15.useMemo)(() => {
5070
+ const resolvedCtas = (0, import_react16.useMemo)(() => {
4891
5071
  const list = ctas ?? DEFAULT_CTAS;
4892
5072
  return list.map((cta) => typeof cta === "string" ? { kind: cta } : cta).filter((cta) => cta.kind !== "all-limits" || headline.count > 0);
4893
5073
  }, [ctas, headline.count]);
@@ -4896,28 +5076,18 @@ var LiteLLMBudgetGauges = ({
4896
5076
  const key = `${cta.kind}-${index}`;
4897
5077
  switch (cta.kind) {
4898
5078
  case "new-key":
4899
- return onCreateKey ? /* @__PURE__ */ import_react15.default.createElement(import_Button6.default, { key, size: "small", variant: "contained", onClick: onCreateKey }, label) : /* @__PURE__ */ import_react15.default.createElement(
4900
- import_Button6.default,
4901
- {
4902
- key,
4903
- size: "small",
4904
- variant: "contained",
4905
- component: import_core_components2.Link,
4906
- to: `${moduleHref}?generate=1`
4907
- },
4908
- label
4909
- );
5079
+ return onCreateKey ? /* @__PURE__ */ import_react16.default.createElement(GenerateKeyButton, { key, size: "small", label, onClick: onCreateKey }) : /* @__PURE__ */ import_react16.default.createElement(GenerateKeyButton, { key, size: "small", label, to: `${moduleHref}?generate=1` });
4910
5080
  case "module":
4911
- return /* @__PURE__ */ import_react15.default.createElement(import_Button6.default, { key, size: "small", variant: "outlined", component: import_core_components2.Link, to: moduleHref }, label);
5081
+ return /* @__PURE__ */ import_react16.default.createElement(import_Button6.default, { key, size: "small", variant: "outlined", component: import_core_components3.Link, to: moduleHref }, label);
4912
5082
  case "all-limits":
4913
- return /* @__PURE__ */ import_react15.default.createElement(
5083
+ return /* @__PURE__ */ import_react16.default.createElement(
4914
5084
  import_Button6.default,
4915
5085
  {
4916
5086
  key,
4917
5087
  size: "small",
4918
5088
  variant: "text",
4919
5089
  onClick: toggleExpanded,
4920
- endIcon: /* @__PURE__ */ import_react15.default.createElement(
5090
+ endIcon: /* @__PURE__ */ import_react16.default.createElement(
4921
5091
  import_icons_material10.ExpandMore,
4922
5092
  {
4923
5093
  sx: {
@@ -4935,14 +5105,22 @@ var LiteLLMBudgetGauges = ({
4935
5105
  }
4936
5106
  };
4937
5107
  const hasFooter = resolvedCtas.length > 0 || !!action;
4938
- return /* @__PURE__ */ import_react15.default.createElement(import_Paper10.default, { sx: { p: 2 } }, /* @__PURE__ */ import_react15.default.createElement(import_Box14.default, { sx: { display: "flex", alignItems: "center", gap: 1, mb: 1.5, minWidth: 0 } }, /* @__PURE__ */ import_react15.default.createElement(import_Typography14.default, { variant: "h6", lineHeight: 1.2, sx: { minWidth: 0, flex: 1 } }, title), !loading && !error && /* @__PURE__ */ import_react15.default.createElement(
5108
+ return /* @__PURE__ */ import_react16.default.createElement(import_Paper10.default, { sx: { p: 2 } }, /* @__PURE__ */ import_react16.default.createElement(import_Box14.default, { sx: { display: "flex", alignItems: "center", gap: 1, mb: 1.5, minWidth: 0 } }, /* @__PURE__ */ import_react16.default.createElement(import_Typography14.default, { variant: "h6", lineHeight: 1.2, sx: { minWidth: 0, flex: 1 } }, title), !loading && !error && /* @__PURE__ */ import_react16.default.createElement(
4939
5109
  StatusPill,
4940
5110
  {
4941
5111
  label: summaryText,
4942
5112
  tone: budgetTone2(headline.closest?.pct ?? 0),
4943
5113
  dot: headline.count > 0
4944
5114
  }
4945
- )), loading && /* @__PURE__ */ import_react15.default.createElement(import_Box14.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 110 }, /* @__PURE__ */ import_react15.default.createElement(import_CircularProgress8.default, { size: 28 })), !loading && error && /* @__PURE__ */ import_react15.default.createElement(import_Alert8.default, { severity: "error", sx: { mt: 0.5 } }, error), !loading && !error && /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement(import_Box14.default, { sx: { display: "flex", alignItems: "flex-start", gap: 1 } }, gauges.map((gauge) => /* @__PURE__ */ import_react15.default.createElement(LevelGauge, { key: gauge.kind, gauge, size, keysHref: keysTabHref }))), /* @__PURE__ */ import_react15.default.createElement(import_Collapse4.default, { in: isExpanded, unmountOnExit: true }, /* @__PURE__ */ import_react15.default.createElement(
5115
+ )), loading && /* @__PURE__ */ import_react16.default.createElement(import_Box14.default, { display: "flex", justifyContent: "center", alignItems: "center", minHeight: 110 }, /* @__PURE__ */ import_react16.default.createElement(import_CircularProgress8.default, { size: 28 })), !loading && error && /* @__PURE__ */ import_react16.default.createElement(import_Alert8.default, { severity: "error", sx: { mt: 0.5 } }, error), !loading && !error && /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(import_Box14.default, { sx: { display: "flex", alignItems: "flex-start", gap: 1 } }, gauges.map((gauge) => /* @__PURE__ */ import_react16.default.createElement(LevelGauge, { key: gauge.kind, gauge, size, keysHref: keysTabHref })), /* @__PURE__ */ import_react16.default.createElement(
5116
+ UsageMiniChart,
5117
+ {
5118
+ data: dailyTokens,
5119
+ totalTokens: mtdTokens,
5120
+ loading: usageLoading,
5121
+ height: size
5122
+ }
5123
+ )), /* @__PURE__ */ import_react16.default.createElement(import_Collapse4.default, { in: isExpanded, unmountOnExit: true }, /* @__PURE__ */ import_react16.default.createElement(
4946
5124
  import_Box14.default,
4947
5125
  {
4948
5126
  sx: {
@@ -4953,7 +5131,7 @@ var LiteLLMBudgetGauges = ({
4953
5131
  overflowY: "auto"
4954
5132
  }
4955
5133
  },
4956
- /* @__PURE__ */ import_react15.default.createElement(LimitListPanel, null, /* @__PURE__ */ import_react15.default.createElement(
5134
+ /* @__PURE__ */ import_react16.default.createElement(LimitListPanel, null, /* @__PURE__ */ import_react16.default.createElement(
4957
5135
  BudgetLimitList,
4958
5136
  {
4959
5137
  limits: expandedLimits,
@@ -4961,7 +5139,7 @@ var LiteLLMBudgetGauges = ({
4961
5139
  keysHref: keysTabHref
4962
5140
  }
4963
5141
  ))
4964
- ))), hasFooter && /* @__PURE__ */ import_react15.default.createElement(
5142
+ ))), hasFooter && /* @__PURE__ */ import_react16.default.createElement(
4965
5143
  import_Box14.default,
4966
5144
  {
4967
5145
  sx: (theme) => ({
@@ -4981,11 +5159,12 @@ var LiteLLMBudgetGauges = ({
4981
5159
 
4982
5160
  // src/index.ts
4983
5161
  init_KeyFormDialog();
5162
+ init_GenerateKeyButton();
4984
5163
 
4985
5164
  // src/components/GenerateKeyDialog.tsx
4986
- var import_react16 = __toESM(require("react"));
5165
+ var import_react17 = __toESM(require("react"));
4987
5166
  init_KeyFormDialog();
4988
- var GenerateKeyDialog = (props) => /* @__PURE__ */ import_react16.default.createElement(
5167
+ var GenerateKeyDialog = (props) => /* @__PURE__ */ import_react17.default.createElement(
4989
5168
  KeyFormDialog,
4990
5169
  {
4991
5170
  open: props.open,