@acarmisc/backstage-plugin-litellm 0.41.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +9 -0
- package/dist/components/KeysTable.d.ts +3 -1
- package/dist/components/ManageTeamDialog.d.ts +4 -0
- package/dist/components/TeamUsage.d.ts +5 -1
- package/dist/index.cjs.js +46 -15
- package/dist/index.cjs.js.map +2 -2
- package/dist/index.esm.js +46 -15
- package/dist/index.esm.js.map +2 -2
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -37,6 +37,11 @@ export interface LiteLlmApiInterface {
|
|
|
37
37
|
}): Promise<TeamInfo>;
|
|
38
38
|
removeTeamMember(teamId: string, userEntityRef: string): Promise<TeamInfo>;
|
|
39
39
|
getVectorStores(): Promise<VectorStoreInfo[]>;
|
|
40
|
+
/** Id → name for every KB and MCP server, for labels only (not allowlist-filtered). */
|
|
41
|
+
getObjectNames(): Promise<{
|
|
42
|
+
vector_stores: VectorStoreInfo[];
|
|
43
|
+
mcp_servers: McpServerInfo[];
|
|
44
|
+
}>;
|
|
40
45
|
setTeamKnowledgeBases(teamId: string, vectorStores: string[]): Promise<TeamInfo>;
|
|
41
46
|
getMcpServers(): Promise<McpServerInfo[]>;
|
|
42
47
|
setTeamMcpServers(teamId: string, mcpServers: string[]): Promise<TeamInfo>;
|
|
@@ -105,6 +110,10 @@ export declare class LiteLlmApi implements LiteLlmApiInterface {
|
|
|
105
110
|
}): Promise<TeamInfo>;
|
|
106
111
|
removeTeamMember(teamId: string, userEntityRef: string): Promise<TeamInfo>;
|
|
107
112
|
getVectorStores(): Promise<VectorStoreInfo[]>;
|
|
113
|
+
getObjectNames(): Promise<{
|
|
114
|
+
vector_stores: VectorStoreInfo[];
|
|
115
|
+
mcp_servers: McpServerInfo[];
|
|
116
|
+
}>;
|
|
108
117
|
setTeamKnowledgeBases(teamId: string, vectorStores: string[]): Promise<TeamInfo>;
|
|
109
118
|
getMcpServers(): Promise<McpServerInfo[]>;
|
|
110
119
|
setTeamMcpServers(teamId: string, mcpServers: string[]): Promise<TeamInfo>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
2
|
import { type KeyFilterType } from '../keyFilter';
|
|
3
|
-
import { VirtualKey } from '../types';
|
|
3
|
+
import { TeamInfo, VirtualKey } from '../types';
|
|
4
4
|
interface KeysTableProps {
|
|
5
5
|
keys: VirtualKey[];
|
|
6
6
|
/** Opens the shared key form dialog in create mode (rendered at page level). */
|
|
@@ -16,6 +16,8 @@ interface KeysTableProps {
|
|
|
16
16
|
}>;
|
|
17
17
|
filter?: KeyFilterType;
|
|
18
18
|
onClearFilter?: () => void;
|
|
19
|
+
/** Used to show team names instead of raw team ids. */
|
|
20
|
+
teams?: TeamInfo[];
|
|
19
21
|
}
|
|
20
22
|
export declare const KeysTable: FC<KeysTableProps>;
|
|
21
23
|
export {};
|
|
@@ -27,12 +27,16 @@ interface ManageTeamDialogProps {
|
|
|
27
27
|
canManageKnowledgeBases?: boolean;
|
|
28
28
|
/** Vector stores the caller may attach (already allowlist-filtered server-side). */
|
|
29
29
|
vectorStores?: VectorStoreInfo[];
|
|
30
|
+
/** Names for labelling attached stores; may include stores not offered in the picker. */
|
|
31
|
+
vectorStoreNames?: VectorStoreInfo[];
|
|
30
32
|
/** Called to replace the team's attached knowledge bases; parent refreshes `team`. */
|
|
31
33
|
onSaveKnowledgeBases?: (vectorStoreIds: string[]) => Promise<void>;
|
|
32
34
|
/** When true, the MCP Servers section (edit mode only) is shown. */
|
|
33
35
|
canManageMcpServers?: boolean;
|
|
34
36
|
/** MCP servers the caller may attach (already allowlist-filtered server-side). */
|
|
35
37
|
mcpServers?: McpServerInfo[];
|
|
38
|
+
/** Names for labelling attached servers; may include servers not offered in the picker. */
|
|
39
|
+
mcpServerNames?: McpServerInfo[];
|
|
36
40
|
/** Called to replace the team's attached MCP servers; parent refreshes `team`. */
|
|
37
41
|
onSaveMcpServers?: (mcpServerIds: string[]) => Promise<void>;
|
|
38
42
|
/** When true, only members section is shown (not budget/models/KB/MCP); title changes; Save becomes Done. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
|
-
import { TeamInfo, TeamMemberUsage, UsageMetrics } from '../types';
|
|
2
|
+
import { McpServerInfo, TeamInfo, TeamMemberUsage, UsageMetrics, VectorStoreInfo } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* Per-member usage for the period, sorted by spend. Dollars are replaced by
|
|
5
5
|
* the share of team spend when the backend hides them.
|
|
@@ -27,6 +27,10 @@ interface TeamUsageProps {
|
|
|
27
27
|
onManageMembers?: (team: TeamInfo) => void;
|
|
28
28
|
/** Teams are synced from an identity provider: show a badge, no write controls. */
|
|
29
29
|
readOnly?: boolean;
|
|
30
|
+
/** Used to show knowledge base names instead of raw ids. */
|
|
31
|
+
vectorStores?: VectorStoreInfo[];
|
|
32
|
+
/** Used to show MCP server names instead of raw ids. */
|
|
33
|
+
mcpServers?: McpServerInfo[];
|
|
30
34
|
}
|
|
31
35
|
export declare const TeamUsage: FC<TeamUsageProps>;
|
|
32
36
|
export {};
|
package/dist/index.cjs.js
CHANGED
|
@@ -287,6 +287,10 @@ var init_api = __esm({
|
|
|
287
287
|
async getVectorStores() {
|
|
288
288
|
return this.get("/vector-stores");
|
|
289
289
|
}
|
|
290
|
+
// Names only, readable by any signed-in user; never used for the picker.
|
|
291
|
+
async getObjectNames() {
|
|
292
|
+
return this.get("/object-names");
|
|
293
|
+
}
|
|
290
294
|
async setTeamKnowledgeBases(teamId, vectorStores) {
|
|
291
295
|
return this.put(
|
|
292
296
|
`/teams/${encodeURIComponent(teamId)}/knowledge-bases`,
|
|
@@ -1782,7 +1786,8 @@ var init_KeysTable = __esm({
|
|
|
1782
1786
|
onDeleteKey,
|
|
1783
1787
|
onPruneExpiredKeys,
|
|
1784
1788
|
filter,
|
|
1785
|
-
onClearFilter
|
|
1789
|
+
onClearFilter,
|
|
1790
|
+
teams
|
|
1786
1791
|
}) => {
|
|
1787
1792
|
const managePermission = (0, import_plugin_permission_react.usePermission)({ permission: import_backstage_plugin_litellm_common.litellmKeyManagePermission });
|
|
1788
1793
|
const revokePermission = (0, import_plugin_permission_react.usePermission)({ permission: import_backstage_plugin_litellm_common.litellmKeyRevokePermission });
|
|
@@ -1810,9 +1815,14 @@ var init_KeysTable = __esm({
|
|
|
1810
1815
|
setSortDirection("asc");
|
|
1811
1816
|
}
|
|
1812
1817
|
};
|
|
1818
|
+
const teamNames = (0, import_react4.useMemo)(
|
|
1819
|
+
() => new Map((teams ?? []).map((t) => [t.team_id, t.team_alias || t.team_id])),
|
|
1820
|
+
[teams]
|
|
1821
|
+
);
|
|
1822
|
+
const teamLabel = (id) => teamNames.get(id) ?? id;
|
|
1813
1823
|
const teamIds = (0, import_react4.useMemo)(
|
|
1814
|
-
() => [...new Set(keys.map((k) => k.team_id).filter((t) => !!t))].sort(),
|
|
1815
|
-
[keys]
|
|
1824
|
+
() => [...new Set(keys.map((k) => k.team_id).filter((t) => !!t))].sort((a, b) => (teamNames.get(a) ?? a).localeCompare(teamNames.get(b) ?? b)),
|
|
1825
|
+
[keys, teamNames]
|
|
1816
1826
|
);
|
|
1817
1827
|
const filteredKeys = (0, import_react4.useMemo)(() => {
|
|
1818
1828
|
let result = keys;
|
|
@@ -1936,7 +1946,7 @@ var init_KeysTable = __esm({
|
|
|
1936
1946
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Typography5.default, { variant: "body2", children: key.key_alias || "\u2014" }),
|
|
1937
1947
|
key.blocked && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusPill, { label: "Blocked", tone: "danger" })
|
|
1938
1948
|
] }) }),
|
|
1939
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Typography5.default, { variant: "body2", color: "text.secondary", children: key.team_id
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Typography5.default, { variant: "body2", color: "text.secondary", children: key.team_id ? teamLabel(key.team_id) : "\u2014" }) }),
|
|
1940
1950
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_Box7.default, { display: "flex", alignItems: "center", gap: 0.5, children: [
|
|
1941
1951
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1942
1952
|
import_Typography5.default,
|
|
@@ -2057,7 +2067,7 @@ var init_KeysTable = __esm({
|
|
|
2057
2067
|
sx: { minWidth: 160 },
|
|
2058
2068
|
children: [
|
|
2059
2069
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_MenuItem.default, { value: "", children: "All teams" }),
|
|
2060
|
-
teamIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_MenuItem.default, { value: id, children: id }, id))
|
|
2070
|
+
teamIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_MenuItem.default, { value: id, children: teamLabel(id) }, id))
|
|
2061
2071
|
]
|
|
2062
2072
|
}
|
|
2063
2073
|
),
|
|
@@ -3239,9 +3249,11 @@ var init_ManageTeamDialog = __esm({
|
|
|
3239
3249
|
onRemoveMember,
|
|
3240
3250
|
canManageKnowledgeBases,
|
|
3241
3251
|
vectorStores,
|
|
3252
|
+
vectorStoreNames,
|
|
3242
3253
|
onSaveKnowledgeBases,
|
|
3243
3254
|
canManageMcpServers,
|
|
3244
3255
|
mcpServers,
|
|
3256
|
+
mcpServerNames,
|
|
3245
3257
|
onSaveMcpServers,
|
|
3246
3258
|
membersOnly,
|
|
3247
3259
|
currentUserId,
|
|
@@ -3510,10 +3522,10 @@ var init_ManageTeamDialog = __esm({
|
|
|
3510
3522
|
const durationOptions = BUDGET_DURATION_OPTIONS.some((o) => o.value === budgetDuration) ? BUDGET_DURATION_OPTIONS : [...BUDGET_DURATION_OPTIONS, { value: budgetDuration, label: budgetDuration }];
|
|
3511
3523
|
const showKnowledgeBases = mode === "edit" && !!canManageKnowledgeBases;
|
|
3512
3524
|
const kbOptions = (vectorStores ?? []).map((v) => v.id);
|
|
3513
|
-
const kbLabel = (id) => (
|
|
3525
|
+
const kbLabel = (id) => (vectorStoreNames ?? []).find((v) => v.id === id)?.name ?? id;
|
|
3514
3526
|
const showMcpServers = mode === "edit" && !!canManageMcpServers;
|
|
3515
3527
|
const mcpOptions = (mcpServers ?? []).map((s) => s.id);
|
|
3516
|
-
const mcpLabel = (id) => (
|
|
3528
|
+
const mcpLabel = (id) => (mcpServerNames ?? []).find((s) => s.id === id)?.name ?? id;
|
|
3517
3529
|
const isRemovalDisabled = (memberUserId, memberRole) => {
|
|
3518
3530
|
if (!membersOnly) return { disabled: false };
|
|
3519
3531
|
if (memberUserId === currentUserId) {
|
|
@@ -5105,7 +5117,7 @@ var init_TeamUsage = __esm({
|
|
|
5105
5117
|
}) })
|
|
5106
5118
|
] }) });
|
|
5107
5119
|
};
|
|
5108
|
-
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand }) => {
|
|
5120
|
+
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
|
|
5109
5121
|
const [expanded, setExpanded] = (0, import_react10.useState)(false);
|
|
5110
5122
|
const chart = useChartTheme();
|
|
5111
5123
|
const handleExpandChange = (newExpanded) => {
|
|
@@ -5172,6 +5184,10 @@ var init_TeamUsage = __esm({
|
|
|
5172
5184
|
children: label
|
|
5173
5185
|
}
|
|
5174
5186
|
);
|
|
5187
|
+
const renderNamedTags = (label, ids, items) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Box14.default, { mb: 2.5, children: [
|
|
5188
|
+
sectionLabel(label),
|
|
5189
|
+
ids?.length ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Box14.default, { display: "flex", gap: 0.5, flexWrap: "wrap", children: ids.map((id) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TagChip, { label: items?.find((i) => i.id === id)?.name ?? id, title: id }, id)) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Typography12.default, { variant: "body2", color: "text.secondary", children: "None configured" })
|
|
5190
|
+
] });
|
|
5175
5191
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Paper8.default, { variant: "outlined", sx: { borderRadius: 2, p: 2.5 }, children: [
|
|
5176
5192
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Box14.default, { display: "flex", alignItems: "center", gap: 1.5, children: [
|
|
5177
5193
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
@@ -5297,6 +5313,8 @@ var init_TeamUsage = __esm({
|
|
|
5297
5313
|
sectionLabel("Models"),
|
|
5298
5314
|
team.models?.length ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Box14.default, { display: "flex", gap: 0.5, flexWrap: "wrap", children: team.models.map((m) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TagChip, { label: m, title: m }, m)) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Typography12.default, { variant: "body2", color: "text.secondary", children: "All models allowed" })
|
|
5299
5315
|
] }),
|
|
5316
|
+
renderNamedTags("Knowledge bases", team.object_permission?.vector_stores, vectorStores),
|
|
5317
|
+
renderNamedTags("MCP servers", team.object_permission?.mcp_servers, mcpServers),
|
|
5300
5318
|
renderDailySpendSection(),
|
|
5301
5319
|
(memberUsageLoading || memberUsage) && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Box14.default, { mb: 2.5, children: [
|
|
5302
5320
|
sectionLabel("Usage by member"),
|
|
@@ -5365,7 +5383,9 @@ var init_TeamUsage = __esm({
|
|
|
5365
5383
|
onTeamExpand,
|
|
5366
5384
|
canManageMembers,
|
|
5367
5385
|
onManageMembers,
|
|
5368
|
-
readOnly
|
|
5386
|
+
readOnly,
|
|
5387
|
+
vectorStores,
|
|
5388
|
+
mcpServers
|
|
5369
5389
|
}) => {
|
|
5370
5390
|
const readOnlyBadge = /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Tooltip5.default, { title: "Teams and memberships are managed in your identity provider. Changes made here would be overwritten, so editing is disabled.", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
5371
5391
|
import_Box14.default,
|
|
@@ -5423,7 +5443,9 @@ var init_TeamUsage = __esm({
|
|
|
5423
5443
|
onEditTeam,
|
|
5424
5444
|
canManageMembers: canManageMembers?.(team),
|
|
5425
5445
|
onManageMembers,
|
|
5426
|
-
onExpand: onTeamExpand
|
|
5446
|
+
onExpand: onTeamExpand,
|
|
5447
|
+
vectorStores,
|
|
5448
|
+
mcpServers
|
|
5427
5449
|
},
|
|
5428
5450
|
team.team_id
|
|
5429
5451
|
)) })
|
|
@@ -6392,12 +6414,16 @@ var init_LiteLLMPage = __esm({
|
|
|
6392
6414
|
const teamMgmtEnabled = liteLlmConfig?.teamManagement?.enabled ?? false;
|
|
6393
6415
|
const objectPermsEnabled = liteLlmConfig?.teamManagement?.objectPermissionsEnabled ?? false;
|
|
6394
6416
|
const { value: vectorStores } = (0, import_react_use2.useAsync)(
|
|
6395
|
-
|
|
6396
|
-
[api
|
|
6417
|
+
() => api.getVectorStores().catch(() => []),
|
|
6418
|
+
[api]
|
|
6397
6419
|
);
|
|
6398
6420
|
const { value: mcpServers } = (0, import_react_use2.useAsync)(
|
|
6399
|
-
|
|
6400
|
-
[api
|
|
6421
|
+
() => api.getMcpServers().catch(() => []),
|
|
6422
|
+
[api]
|
|
6423
|
+
);
|
|
6424
|
+
const { value: objectNames } = (0, import_react_use2.useAsync)(
|
|
6425
|
+
() => api.getObjectNames().catch(() => ({ vector_stores: [], mcp_servers: [] })),
|
|
6426
|
+
[api]
|
|
6401
6427
|
);
|
|
6402
6428
|
const teams = (0, import_react13.useMemo)(() => {
|
|
6403
6429
|
if (!allTeams?.length) return [];
|
|
@@ -6723,7 +6749,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6723
6749
|
onDeleteKey: handleDeleteKey,
|
|
6724
6750
|
onPruneExpiredKeys: handlePruneExpiredKeys,
|
|
6725
6751
|
filter,
|
|
6726
|
-
onClearFilter: clearFilter
|
|
6752
|
+
onClearFilter: clearFilter,
|
|
6753
|
+
teams: allTeams ?? []
|
|
6727
6754
|
}
|
|
6728
6755
|
);
|
|
6729
6756
|
})(),
|
|
@@ -6754,6 +6781,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6754
6781
|
onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
|
|
6755
6782
|
canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
|
|
6756
6783
|
onCreateTeam: () => setManageTeam({ mode: "create" }),
|
|
6784
|
+
vectorStores: objectNames?.vector_stores ?? [],
|
|
6785
|
+
mcpServers: objectNames?.mcp_servers ?? [],
|
|
6757
6786
|
canManageMembers: (t) => teamMgmtEnabled && canManageMembers && isTeamMemberManager(t, userInfo?.user_id, memberManagerRoles, readOnly),
|
|
6758
6787
|
onManageMembers: (t) => setManageTeam({ mode: "members", team: t }),
|
|
6759
6788
|
readOnly,
|
|
@@ -6885,6 +6914,7 @@ var init_LiteLLMPage = __esm({
|
|
|
6885
6914
|
},
|
|
6886
6915
|
canManageKnowledgeBases: teamMgmtEnabled && objectPermsEnabled && canManageKnowledgeBases,
|
|
6887
6916
|
vectorStores: vectorStores ?? [],
|
|
6917
|
+
vectorStoreNames: objectNames?.vector_stores ?? [],
|
|
6888
6918
|
onSaveKnowledgeBases: async (vectorStoreIds) => {
|
|
6889
6919
|
if (!manageTeam?.team) return;
|
|
6890
6920
|
try {
|
|
@@ -6903,6 +6933,7 @@ var init_LiteLLMPage = __esm({
|
|
|
6903
6933
|
},
|
|
6904
6934
|
canManageMcpServers: teamMgmtEnabled && objectPermsEnabled && canManageMcpServers,
|
|
6905
6935
|
mcpServers: mcpServers ?? [],
|
|
6936
|
+
mcpServerNames: objectNames?.mcp_servers ?? [],
|
|
6906
6937
|
onSaveMcpServers: async (mcpServerIds) => {
|
|
6907
6938
|
if (!manageTeam?.team) return;
|
|
6908
6939
|
try {
|