@acarmisc/backstage-plugin-litellm 0.42.0 → 0.44.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 +13 -1
- package/dist/components/ManageTeamDialog.d.ts +4 -0
- package/dist/components/TeamUsage.d.ts +11 -1
- package/dist/index.cjs.js +96 -7
- package/dist/index.cjs.js.map +2 -2
- package/dist/index.esm.js +96 -7
- package/dist/index.esm.js.map +2 -2
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
package/dist/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FetchApi, type DiscoveryApi } from '@backstage/frontend-plugin-api';
|
|
2
|
-
import { UserInfo, VirtualKey, ModelInfo, UsageMetrics, TeamMemberUsage, TeamInfo, GenerateKeyRequest, GenerateKeyResponse, UpdateKeyRequest, AuditLogsParams, PaginatedAuditLogs, SpendLogsParams, PaginatedSpendLogs, LiteLlmConfig, QualityResponse, VectorStoreInfo, McpServerInfo, CreateTeamRequest, CreateTeamResponse, UpdateTeamRequest } from './types';
|
|
2
|
+
import { UserInfo, VirtualKey, ModelInfo, UsageMetrics, TeamMemberUsage, TeamKeyUsage, TeamInfo, GenerateKeyRequest, GenerateKeyResponse, UpdateKeyRequest, AuditLogsParams, PaginatedAuditLogs, SpendLogsParams, PaginatedSpendLogs, LiteLlmConfig, QualityResponse, VectorStoreInfo, McpServerInfo, CreateTeamRequest, CreateTeamResponse, UpdateTeamRequest } from './types';
|
|
3
3
|
export declare class ApiError extends Error {
|
|
4
4
|
body: unknown;
|
|
5
5
|
status: number;
|
|
@@ -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>;
|
|
@@ -44,6 +49,8 @@ export interface LiteLlmApiInterface {
|
|
|
44
49
|
getTeamUsage(teamId: string, startDate: string, endDate: string): Promise<UsageMetrics>;
|
|
45
50
|
/** Per-member breakdown; rejects (403/404) when the caller may not see it. */
|
|
46
51
|
getTeamMemberUsage(teamId: string, startDate: string, endDate: string): Promise<TeamMemberUsage>;
|
|
52
|
+
/** A team's keys with per-key usage; same access rules as the per-member breakdown. */
|
|
53
|
+
getTeamKeyUsage(teamId: string, startDate: string, endDate: string): Promise<TeamKeyUsage>;
|
|
47
54
|
getAuditLogs(params: AuditLogsParams): Promise<PaginatedAuditLogs>;
|
|
48
55
|
getSpendLogs(params: SpendLogsParams): Promise<PaginatedSpendLogs>;
|
|
49
56
|
/** Langfuse quality summary; `{configured:false}` when Langfuse is off. */
|
|
@@ -105,12 +112,17 @@ export declare class LiteLlmApi implements LiteLlmApiInterface {
|
|
|
105
112
|
}): Promise<TeamInfo>;
|
|
106
113
|
removeTeamMember(teamId: string, userEntityRef: string): Promise<TeamInfo>;
|
|
107
114
|
getVectorStores(): Promise<VectorStoreInfo[]>;
|
|
115
|
+
getObjectNames(): Promise<{
|
|
116
|
+
vector_stores: VectorStoreInfo[];
|
|
117
|
+
mcp_servers: McpServerInfo[];
|
|
118
|
+
}>;
|
|
108
119
|
setTeamKnowledgeBases(teamId: string, vectorStores: string[]): Promise<TeamInfo>;
|
|
109
120
|
getMcpServers(): Promise<McpServerInfo[]>;
|
|
110
121
|
setTeamMcpServers(teamId: string, mcpServers: string[]): Promise<TeamInfo>;
|
|
111
122
|
getUsage(startDate: string, endDate: string): Promise<UsageMetrics>;
|
|
112
123
|
getTeamUsage(teamId: string, startDate: string, endDate: string): Promise<UsageMetrics>;
|
|
113
124
|
getTeamMemberUsage(teamId: string, startDate: string, endDate: string): Promise<TeamMemberUsage>;
|
|
125
|
+
getTeamKeyUsage(teamId: string, startDate: string, endDate: string): Promise<TeamKeyUsage>;
|
|
114
126
|
getSpendLogs(params: SpendLogsParams): Promise<PaginatedSpendLogs>;
|
|
115
127
|
getQuality(params: SpendLogsParams): Promise<QualityResponse>;
|
|
116
128
|
getConfig(): Promise<LiteLlmConfig>;
|
|
@@ -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 { McpServerInfo, TeamInfo, TeamMemberUsage, UsageMetrics, VectorStoreInfo } from '../types';
|
|
2
|
+
import { McpServerInfo, TeamInfo, TeamKeyUsage, 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.
|
|
@@ -7,6 +7,13 @@ import { McpServerInfo, TeamInfo, TeamMemberUsage, UsageMetrics, VectorStoreInfo
|
|
|
7
7
|
export declare const MemberUsageTable: FC<{
|
|
8
8
|
usage: TeamMemberUsage;
|
|
9
9
|
}>;
|
|
10
|
+
/**
|
|
11
|
+
* A team's keys with the period's usage, for team leads. The backend never
|
|
12
|
+
* sends secrets; dollars are dropped when it hides them.
|
|
13
|
+
*/
|
|
14
|
+
export declare const TeamKeyUsageTable: FC<{
|
|
15
|
+
usage: TeamKeyUsage;
|
|
16
|
+
}>;
|
|
10
17
|
interface TeamUsageProps {
|
|
11
18
|
teams: TeamInfo[];
|
|
12
19
|
loading: boolean;
|
|
@@ -15,6 +22,9 @@ interface TeamUsageProps {
|
|
|
15
22
|
/** Per-member breakdown for a team; null hides the section. */
|
|
16
23
|
getTeamMemberUsage?: (teamId: string) => TeamMemberUsage | null;
|
|
17
24
|
getTeamMemberUsageLoading?: (teamId: string) => boolean;
|
|
25
|
+
/** Per-key usage for a team; null hides the section. */
|
|
26
|
+
getTeamKeyUsage?: (teamId: string) => TeamKeyUsage | null;
|
|
27
|
+
getTeamKeyUsageLoading?: (teamId: string) => boolean;
|
|
18
28
|
canManage?: boolean;
|
|
19
29
|
onEditTeam?: (team: TeamInfo) => void;
|
|
20
30
|
/** When true (with `onCreateTeam`), a "Create Team" action renders in the section header. */
|
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`,
|
|
@@ -317,6 +321,12 @@ var init_api = __esm({
|
|
|
317
321
|
end_date: endDate
|
|
318
322
|
});
|
|
319
323
|
}
|
|
324
|
+
async getTeamKeyUsage(teamId, startDate, endDate) {
|
|
325
|
+
return this.get(`/teams/${encodeURIComponent(teamId)}/usage/keys`, {
|
|
326
|
+
start_date: startDate,
|
|
327
|
+
end_date: endDate
|
|
328
|
+
});
|
|
329
|
+
}
|
|
320
330
|
async getSpendLogs(params) {
|
|
321
331
|
const strParams = {
|
|
322
332
|
start_date: params.startDate,
|
|
@@ -3245,9 +3255,11 @@ var init_ManageTeamDialog = __esm({
|
|
|
3245
3255
|
onRemoveMember,
|
|
3246
3256
|
canManageKnowledgeBases,
|
|
3247
3257
|
vectorStores,
|
|
3258
|
+
vectorStoreNames,
|
|
3248
3259
|
onSaveKnowledgeBases,
|
|
3249
3260
|
canManageMcpServers,
|
|
3250
3261
|
mcpServers,
|
|
3262
|
+
mcpServerNames,
|
|
3251
3263
|
onSaveMcpServers,
|
|
3252
3264
|
membersOnly,
|
|
3253
3265
|
currentUserId,
|
|
@@ -3516,10 +3528,10 @@ var init_ManageTeamDialog = __esm({
|
|
|
3516
3528
|
const durationOptions = BUDGET_DURATION_OPTIONS.some((o) => o.value === budgetDuration) ? BUDGET_DURATION_OPTIONS : [...BUDGET_DURATION_OPTIONS, { value: budgetDuration, label: budgetDuration }];
|
|
3517
3529
|
const showKnowledgeBases = mode === "edit" && !!canManageKnowledgeBases;
|
|
3518
3530
|
const kbOptions = (vectorStores ?? []).map((v) => v.id);
|
|
3519
|
-
const kbLabel = (id) => (
|
|
3531
|
+
const kbLabel = (id) => (vectorStoreNames ?? []).find((v) => v.id === id)?.name ?? id;
|
|
3520
3532
|
const showMcpServers = mode === "edit" && !!canManageMcpServers;
|
|
3521
3533
|
const mcpOptions = (mcpServers ?? []).map((s) => s.id);
|
|
3522
|
-
const mcpLabel = (id) => (
|
|
3534
|
+
const mcpLabel = (id) => (mcpServerNames ?? []).find((s) => s.id === id)?.name ?? id;
|
|
3523
3535
|
const isRemovalDisabled = (memberUserId, memberRole) => {
|
|
3524
3536
|
if (!membersOnly) return { disabled: false };
|
|
3525
3537
|
if (memberUserId === currentUserId) {
|
|
@@ -5048,7 +5060,7 @@ function budgetStatValue(hidden, budget) {
|
|
|
5048
5060
|
if (budget > 0) return fmtUsd2(budget);
|
|
5049
5061
|
return "Unlimited";
|
|
5050
5062
|
}
|
|
5051
|
-
var import_react10, import_Paper8, import_Box14, import_Typography12, import_Skeleton5, import_Divider3, import_Table4, import_TableBody4, import_TableCell4, import_TableHead4, import_TableRow4, import_TableContainer4, import_Collapse2, import_IconButton6, import_Button6, import_CircularProgress4, import_styles10, import_Tooltip5, import_icons_material7, import_recharts2, import_jsx_runtime15, fmtUsd2, monoSx, MemberUsageTable, TeamCard, TeamUsage;
|
|
5063
|
+
var import_react10, import_Paper8, import_Box14, import_Typography12, import_Skeleton5, import_Divider3, import_Table4, import_TableBody4, import_TableCell4, import_TableHead4, import_TableRow4, import_TableContainer4, import_Collapse2, import_IconButton6, import_Button6, import_CircularProgress4, import_styles10, import_Tooltip5, import_icons_material7, import_recharts2, import_jsx_runtime15, fmtUsd2, monoSx, MemberUsageTable, TeamKeyUsageTable, TeamCard, TeamUsage;
|
|
5052
5064
|
var init_TeamUsage = __esm({
|
|
5053
5065
|
"src/components/TeamUsage.tsx"() {
|
|
5054
5066
|
"use strict";
|
|
@@ -5111,7 +5123,47 @@ var init_TeamUsage = __esm({
|
|
|
5111
5123
|
}) })
|
|
5112
5124
|
] }) });
|
|
5113
5125
|
};
|
|
5114
|
-
|
|
5126
|
+
TeamKeyUsageTable = ({ usage }) => {
|
|
5127
|
+
const hidden = usage.budget_hidden === true;
|
|
5128
|
+
if (!usage.keys.length) {
|
|
5129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Typography12.default, { variant: "body2", color: "text.secondary", children: "This team has no keys." });
|
|
5130
|
+
}
|
|
5131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableContainer4.default, { component: import_Paper8.default, variant: "outlined", sx: { borderRadius: 1.5 }, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Table4.default, { size: "small", sx: dataTableSx, "aria-label": "Keys by member", children: [
|
|
5132
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableHead4.default, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_TableRow4.default, { children: [
|
|
5133
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { children: "Key" }),
|
|
5134
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { children: "Owner" }),
|
|
5135
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { children: "Created" }),
|
|
5136
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { children: "Status" }),
|
|
5137
|
+
!hidden && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { align: "right", children: "Spend" }),
|
|
5138
|
+
!hidden && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { align: "right", children: "Budget" }),
|
|
5139
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { align: "right", children: "Tokens" }),
|
|
5140
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { align: "right", children: "Requests" })
|
|
5141
|
+
] }) }),
|
|
5142
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableBody4.default, { children: usage.keys.map((k) => {
|
|
5143
|
+
const owner = k.display_name ?? k.user_email ?? k.user_id;
|
|
5144
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_TableRow4.default, { children: [
|
|
5145
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_TableCell4.default, { children: [
|
|
5146
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Typography12.default, { variant: "body2", children: k.key_alias ?? k.key }),
|
|
5147
|
+
k.key_alias && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Typography12.default, { variant: "caption", color: "text.secondary", sx: monoSx, children: k.key })
|
|
5148
|
+
] }),
|
|
5149
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { children: owner ?? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Typography12.default, { variant: "body2", color: "text.secondary", children: "\u2014" }) }),
|
|
5150
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { children: fmtDateShort(k.created_at) }),
|
|
5151
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5152
|
+
StatusPill,
|
|
5153
|
+
{
|
|
5154
|
+
label: k.blocked ? "Blocked" : "Active",
|
|
5155
|
+
tone: k.blocked ? "danger" : "success"
|
|
5156
|
+
}
|
|
5157
|
+
) }),
|
|
5158
|
+
!hidden && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { align: "right", children: fmtUsd2(k.spend) }),
|
|
5159
|
+
!hidden && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { align: "right", children: k.max_budget === void 0 ? "Unlimited" : fmtUsd2(k.max_budget) }),
|
|
5160
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { align: "right", children: fmtCompact(k.total_tokens) }),
|
|
5161
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_TableCell4.default, { align: "right", children: k.api_requests.toLocaleString() })
|
|
5162
|
+
] }, k.key);
|
|
5163
|
+
}) })
|
|
5164
|
+
] }) });
|
|
5165
|
+
};
|
|
5166
|
+
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, keyUsage, keyUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
|
|
5115
5167
|
const [expanded, setExpanded] = (0, import_react10.useState)(false);
|
|
5116
5168
|
const chart = useChartTheme();
|
|
5117
5169
|
const handleExpandChange = (newExpanded) => {
|
|
@@ -5314,6 +5366,10 @@ var init_TeamUsage = __esm({
|
|
|
5314
5366
|
sectionLabel("Usage by member"),
|
|
5315
5367
|
memberUsage ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MemberUsageTable, { usage: memberUsage }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Box14.default, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_CircularProgress4.default, { size: 22 }) })
|
|
5316
5368
|
] }),
|
|
5369
|
+
(keyUsageLoading || keyUsage) && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Box14.default, { mb: 2.5, children: [
|
|
5370
|
+
sectionLabel("Keys by member"),
|
|
5371
|
+
keyUsage ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TeamKeyUsageTable, { usage: keyUsage }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Box14.default, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_CircularProgress4.default, { size: 22 }) })
|
|
5372
|
+
] }),
|
|
5317
5373
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Box14.default, { children: [
|
|
5318
5374
|
sectionLabel("Members"),
|
|
5319
5375
|
team.members_with_roles?.length ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
@@ -5370,6 +5426,8 @@ var init_TeamUsage = __esm({
|
|
|
5370
5426
|
getTeamUsageLoading,
|
|
5371
5427
|
getTeamMemberUsage,
|
|
5372
5428
|
getTeamMemberUsageLoading,
|
|
5429
|
+
getTeamKeyUsage,
|
|
5430
|
+
getTeamKeyUsageLoading,
|
|
5373
5431
|
canManage,
|
|
5374
5432
|
onEditTeam,
|
|
5375
5433
|
canCreate,
|
|
@@ -5433,6 +5491,8 @@ var init_TeamUsage = __esm({
|
|
|
5433
5491
|
usageLoading: getTeamUsageLoading(team.team_id),
|
|
5434
5492
|
memberUsage: getTeamMemberUsage?.(team.team_id) ?? null,
|
|
5435
5493
|
memberUsageLoading: getTeamMemberUsageLoading?.(team.team_id) ?? false,
|
|
5494
|
+
keyUsage: getTeamKeyUsage?.(team.team_id) ?? null,
|
|
5495
|
+
keyUsageLoading: getTeamKeyUsageLoading?.(team.team_id) ?? false,
|
|
5436
5496
|
canManage,
|
|
5437
5497
|
onEditTeam,
|
|
5438
5498
|
canManageMembers: canManageMembers?.(team),
|
|
@@ -6379,6 +6439,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6379
6439
|
const [teamUsageLoading, setTeamUsageLoading] = (0, import_react13.useState)({});
|
|
6380
6440
|
const [memberUsageCache, setMemberUsageCache] = (0, import_react13.useState)({});
|
|
6381
6441
|
const [memberUsageLoading, setMemberUsageLoading] = (0, import_react13.useState)({});
|
|
6442
|
+
const [keyUsageCache, setKeyUsageCache] = (0, import_react13.useState)({});
|
|
6443
|
+
const [keyUsageLoading, setKeyUsageLoading] = (0, import_react13.useState)({});
|
|
6382
6444
|
const { value: userInfo, loading: userLoading, error: userError } = (0, import_react_use2.useAsync)(
|
|
6383
6445
|
() => api.getUserInfo(),
|
|
6384
6446
|
[api]
|
|
@@ -6415,6 +6477,10 @@ var init_LiteLLMPage = __esm({
|
|
|
6415
6477
|
() => api.getMcpServers().catch(() => []),
|
|
6416
6478
|
[api]
|
|
6417
6479
|
);
|
|
6480
|
+
const { value: objectNames } = (0, import_react_use2.useAsync)(
|
|
6481
|
+
() => api.getObjectNames().catch(() => ({ vector_stores: [], mcp_servers: [] })),
|
|
6482
|
+
[api]
|
|
6483
|
+
);
|
|
6418
6484
|
const teams = (0, import_react13.useMemo)(() => {
|
|
6419
6485
|
if (!allTeams?.length) return [];
|
|
6420
6486
|
if (!userInfo) return allTeams;
|
|
@@ -6441,6 +6507,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6441
6507
|
setTeamUsageLoading({});
|
|
6442
6508
|
setMemberUsageCache({});
|
|
6443
6509
|
setMemberUsageLoading({});
|
|
6510
|
+
setKeyUsageCache({});
|
|
6511
|
+
setKeyUsageLoading({});
|
|
6444
6512
|
}, [setDateRange, setCurrentPreset]);
|
|
6445
6513
|
const loadTeamUsage = (0, import_react13.useCallback)(async (teamId) => {
|
|
6446
6514
|
if (teamUsageCache[teamId] !== void 0 || teamUsageLoading[teamId]) return;
|
|
@@ -6470,6 +6538,20 @@ var init_LiteLLMPage = __esm({
|
|
|
6470
6538
|
setMemberUsageLoading((prev) => ({ ...prev, [teamId]: false }));
|
|
6471
6539
|
}
|
|
6472
6540
|
}, [api, dateRange, memberUsageCache, memberUsageLoading]);
|
|
6541
|
+
const loadKeyUsage = (0, import_react13.useCallback)(async (teamId) => {
|
|
6542
|
+
if (keyUsageCache[teamId] !== void 0 || keyUsageLoading[teamId]) return;
|
|
6543
|
+
setKeyUsageLoading((prev) => ({ ...prev, [teamId]: true }));
|
|
6544
|
+
try {
|
|
6545
|
+
const startDate = toLocalDay(dateRange.start);
|
|
6546
|
+
const endDate = toLocalDay(dateRange.end);
|
|
6547
|
+
const data = await api.getTeamKeyUsage(teamId, startDate, endDate);
|
|
6548
|
+
setKeyUsageCache((prev) => ({ ...prev, [teamId]: data }));
|
|
6549
|
+
} catch {
|
|
6550
|
+
setKeyUsageCache((prev) => ({ ...prev, [teamId]: null }));
|
|
6551
|
+
} finally {
|
|
6552
|
+
setKeyUsageLoading((prev) => ({ ...prev, [teamId]: false }));
|
|
6553
|
+
}
|
|
6554
|
+
}, [api, dateRange, keyUsageCache, keyUsageLoading]);
|
|
6473
6555
|
const allowedModels = (0, import_react13.useMemo)(() => {
|
|
6474
6556
|
if (!allModels?.length) return [];
|
|
6475
6557
|
const userModels = userInfo?.models;
|
|
@@ -6767,18 +6849,23 @@ var init_LiteLLMPage = __esm({
|
|
|
6767
6849
|
getTeamUsageLoading: (teamId) => teamUsageLoading[teamId] ?? false,
|
|
6768
6850
|
getTeamMemberUsage: (teamId) => memberUsageCache[teamId] ?? null,
|
|
6769
6851
|
getTeamMemberUsageLoading: (teamId) => memberUsageLoading[teamId] ?? false,
|
|
6852
|
+
getTeamKeyUsage: (teamId) => keyUsageCache[teamId] ?? null,
|
|
6853
|
+
getTeamKeyUsageLoading: (teamId) => keyUsageLoading[teamId] ?? false,
|
|
6770
6854
|
canManage: teamMgmtEnabled && canManageTeam && !readOnly,
|
|
6771
6855
|
onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
|
|
6772
6856
|
canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
|
|
6773
6857
|
onCreateTeam: () => setManageTeam({ mode: "create" }),
|
|
6774
|
-
vectorStores:
|
|
6775
|
-
mcpServers:
|
|
6858
|
+
vectorStores: objectNames?.vector_stores ?? [],
|
|
6859
|
+
mcpServers: objectNames?.mcp_servers ?? [],
|
|
6776
6860
|
canManageMembers: (t) => teamMgmtEnabled && canManageMembers && isTeamMemberManager(t, userInfo?.user_id, memberManagerRoles, readOnly),
|
|
6777
6861
|
onManageMembers: (t) => setManageTeam({ mode: "members", team: t }),
|
|
6778
6862
|
readOnly,
|
|
6779
6863
|
onTeamExpand: (team) => {
|
|
6780
6864
|
loadTeamUsage(team.team_id);
|
|
6781
|
-
if (liteLlmConfig?.teamUsage?.memberBreakdown)
|
|
6865
|
+
if (liteLlmConfig?.teamUsage?.memberBreakdown) {
|
|
6866
|
+
loadMemberUsage(team.team_id);
|
|
6867
|
+
loadKeyUsage(team.team_id);
|
|
6868
|
+
}
|
|
6782
6869
|
}
|
|
6783
6870
|
}
|
|
6784
6871
|
);
|
|
@@ -6904,6 +6991,7 @@ var init_LiteLLMPage = __esm({
|
|
|
6904
6991
|
},
|
|
6905
6992
|
canManageKnowledgeBases: teamMgmtEnabled && objectPermsEnabled && canManageKnowledgeBases,
|
|
6906
6993
|
vectorStores: vectorStores ?? [],
|
|
6994
|
+
vectorStoreNames: objectNames?.vector_stores ?? [],
|
|
6907
6995
|
onSaveKnowledgeBases: async (vectorStoreIds) => {
|
|
6908
6996
|
if (!manageTeam?.team) return;
|
|
6909
6997
|
try {
|
|
@@ -6922,6 +7010,7 @@ var init_LiteLLMPage = __esm({
|
|
|
6922
7010
|
},
|
|
6923
7011
|
canManageMcpServers: teamMgmtEnabled && objectPermsEnabled && canManageMcpServers,
|
|
6924
7012
|
mcpServers: mcpServers ?? [],
|
|
7013
|
+
mcpServerNames: objectNames?.mcp_servers ?? [],
|
|
6925
7014
|
onSaveMcpServers: async (mcpServerIds) => {
|
|
6926
7015
|
if (!manageTeam?.team) return;
|
|
6927
7016
|
try {
|