@acarmisc/backstage-plugin-litellm-common 0.1.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/budgets.d.ts +16 -0
- package/dist/budgets.js +41 -0
- package/dist/index.cjs.js +219 -0
- package/dist/index.cjs.js.map +7 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/keySchemas.d.ts +88 -0
- package/dist/keySchemas.js +126 -0
- package/dist/modelAccess.d.ts +15 -0
- package/dist/modelAccess.js +24 -0
- package/dist/permissions.d.ts +13 -0
- package/dist/permissions.js +67 -0
- package/dist/types.d.ts +216 -0
- package/dist/types.js +2 -0
- package/package.json +44 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Budget warning threshold (percent of cap). */
|
|
2
|
+
export declare const BUDGET_WARNING_PCT = 80;
|
|
3
|
+
/** Budget danger threshold (percent of cap, at or over cap). */
|
|
4
|
+
export declare const BUDGET_DANGER_PCT = 100;
|
|
5
|
+
/** Consumption status derived from spend vs. cap. */
|
|
6
|
+
export type BudgetStatus = 'ok' | 'near' | 'over';
|
|
7
|
+
/**
|
|
8
|
+
* Compute budget status from spend percentage of cap.
|
|
9
|
+
* Thresholds: near >= 80%, over >= 100%.
|
|
10
|
+
*/
|
|
11
|
+
export declare function budgetStatusForPct(pct: number): BudgetStatus;
|
|
12
|
+
/**
|
|
13
|
+
* Format a duration string to a human-readable label.
|
|
14
|
+
* E.g., "1d" → "1 Day", "7d" → "7 Days".
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatDurationLabel(duration: string): string;
|
package/dist/budgets.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BUDGET_DANGER_PCT = exports.BUDGET_WARNING_PCT = void 0;
|
|
4
|
+
exports.budgetStatusForPct = budgetStatusForPct;
|
|
5
|
+
exports.formatDurationLabel = formatDurationLabel;
|
|
6
|
+
/** Budget warning threshold (percent of cap). */
|
|
7
|
+
exports.BUDGET_WARNING_PCT = 80;
|
|
8
|
+
/** Budget danger threshold (percent of cap, at or over cap). */
|
|
9
|
+
exports.BUDGET_DANGER_PCT = 100;
|
|
10
|
+
/**
|
|
11
|
+
* Compute budget status from spend percentage of cap.
|
|
12
|
+
* Thresholds: near >= 80%, over >= 100%.
|
|
13
|
+
*/
|
|
14
|
+
function budgetStatusForPct(pct) {
|
|
15
|
+
if (pct >= exports.BUDGET_DANGER_PCT)
|
|
16
|
+
return 'over';
|
|
17
|
+
if (pct >= exports.BUDGET_WARNING_PCT)
|
|
18
|
+
return 'near';
|
|
19
|
+
return 'ok';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Format a duration string to a human-readable label.
|
|
23
|
+
* E.g., "1d" → "1 Day", "7d" → "7 Days".
|
|
24
|
+
*/
|
|
25
|
+
function formatDurationLabel(duration) {
|
|
26
|
+
const match = /^(\d+)([smhdwy])$/.exec(duration);
|
|
27
|
+
if (!match)
|
|
28
|
+
return duration;
|
|
29
|
+
const [, num, unit] = match;
|
|
30
|
+
const n = Number(num);
|
|
31
|
+
const unitLabels = {
|
|
32
|
+
s: 'Second',
|
|
33
|
+
m: 'Minute',
|
|
34
|
+
h: 'Hour',
|
|
35
|
+
d: 'Day',
|
|
36
|
+
w: 'Week',
|
|
37
|
+
y: 'Year',
|
|
38
|
+
};
|
|
39
|
+
const label = unitLabels[unit] || unit;
|
|
40
|
+
return n === 1 ? `1 ${label}` : `${n} ${label}s`;
|
|
41
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ALL_PROXY_MODELS: () => ALL_PROXY_MODELS,
|
|
24
|
+
BUDGET_DANGER_PCT: () => BUDGET_DANGER_PCT,
|
|
25
|
+
BUDGET_WARNING_PCT: () => BUDGET_WARNING_PCT,
|
|
26
|
+
DEFAULT_KEY_DURATIONS: () => DEFAULT_KEY_DURATIONS,
|
|
27
|
+
RESERVED_METADATA_KEYS: () => RESERVED_METADATA_KEYS,
|
|
28
|
+
budgetStatusForPct: () => budgetStatusForPct,
|
|
29
|
+
createGenerateKeyInputSchema: () => createGenerateKeyInputSchema,
|
|
30
|
+
createUpdateKeyInputSchema: () => createUpdateKeyInputSchema,
|
|
31
|
+
formatDurationLabel: () => formatDurationLabel,
|
|
32
|
+
isModelAllowed: () => isModelAllowed,
|
|
33
|
+
litellmAuditReadPermission: () => litellmAuditReadPermission,
|
|
34
|
+
litellmKeyCreatePermission: () => litellmKeyCreatePermission,
|
|
35
|
+
litellmKeyManagePermission: () => litellmKeyManagePermission,
|
|
36
|
+
litellmKeyResetSpendPermission: () => litellmKeyResetSpendPermission,
|
|
37
|
+
litellmKeyRevokePermission: () => litellmKeyRevokePermission,
|
|
38
|
+
litellmKeyUnblockPermission: () => litellmKeyUnblockPermission,
|
|
39
|
+
litellmPermissions: () => litellmPermissions,
|
|
40
|
+
litellmTeamCreatePermission: () => litellmTeamCreatePermission,
|
|
41
|
+
litellmTeamDeletePermission: () => litellmTeamDeletePermission,
|
|
42
|
+
litellmTeamKnowledgebaseManagePermission: () => litellmTeamKnowledgebaseManagePermission,
|
|
43
|
+
litellmTeamManagePermission: () => litellmTeamManagePermission,
|
|
44
|
+
litellmTeamMcpManagePermission: () => litellmTeamMcpManagePermission,
|
|
45
|
+
litellmTeamMembersManagePermission: () => litellmTeamMembersManagePermission,
|
|
46
|
+
reservedMetadataKeys: () => reservedMetadataKeys
|
|
47
|
+
});
|
|
48
|
+
module.exports = __toCommonJS(index_exports);
|
|
49
|
+
|
|
50
|
+
// src/permissions.ts
|
|
51
|
+
var import_plugin_permission_common = require("@backstage/plugin-permission-common");
|
|
52
|
+
var litellmKeyCreatePermission = (0, import_plugin_permission_common.createPermission)({
|
|
53
|
+
name: "litellm.key.create",
|
|
54
|
+
attributes: { action: "create" }
|
|
55
|
+
});
|
|
56
|
+
var litellmKeyRevokePermission = (0, import_plugin_permission_common.createPermission)({
|
|
57
|
+
name: "litellm.key.revoke",
|
|
58
|
+
attributes: { action: "delete" }
|
|
59
|
+
});
|
|
60
|
+
var litellmKeyManagePermission = (0, import_plugin_permission_common.createPermission)({
|
|
61
|
+
name: "litellm.key.manage",
|
|
62
|
+
attributes: { action: "update" }
|
|
63
|
+
});
|
|
64
|
+
var litellmKeyResetSpendPermission = (0, import_plugin_permission_common.createPermission)({
|
|
65
|
+
name: "litellm.key.resetSpend",
|
|
66
|
+
attributes: { action: "update" }
|
|
67
|
+
});
|
|
68
|
+
var litellmKeyUnblockPermission = (0, import_plugin_permission_common.createPermission)({
|
|
69
|
+
name: "litellm.key.unblock",
|
|
70
|
+
attributes: { action: "update" }
|
|
71
|
+
});
|
|
72
|
+
var litellmAuditReadPermission = (0, import_plugin_permission_common.createPermission)({
|
|
73
|
+
name: "litellm.audit.read",
|
|
74
|
+
attributes: { action: "read" }
|
|
75
|
+
});
|
|
76
|
+
var litellmTeamCreatePermission = (0, import_plugin_permission_common.createPermission)({
|
|
77
|
+
name: "litellm.team.create",
|
|
78
|
+
attributes: { action: "create" }
|
|
79
|
+
});
|
|
80
|
+
var litellmTeamManagePermission = (0, import_plugin_permission_common.createPermission)({
|
|
81
|
+
name: "litellm.team.manage",
|
|
82
|
+
attributes: { action: "update" }
|
|
83
|
+
});
|
|
84
|
+
var litellmTeamMembersManagePermission = (0, import_plugin_permission_common.createPermission)({
|
|
85
|
+
name: "litellm.team.members.manage",
|
|
86
|
+
attributes: { action: "update" }
|
|
87
|
+
});
|
|
88
|
+
var litellmTeamKnowledgebaseManagePermission = (0, import_plugin_permission_common.createPermission)({
|
|
89
|
+
name: "litellm.team.knowledgebase.manage",
|
|
90
|
+
attributes: { action: "update" }
|
|
91
|
+
});
|
|
92
|
+
var litellmTeamMcpManagePermission = (0, import_plugin_permission_common.createPermission)({
|
|
93
|
+
name: "litellm.team.mcp.manage",
|
|
94
|
+
attributes: { action: "update" }
|
|
95
|
+
});
|
|
96
|
+
var litellmTeamDeletePermission = (0, import_plugin_permission_common.createPermission)({
|
|
97
|
+
name: "litellm.team.delete",
|
|
98
|
+
attributes: { action: "delete" }
|
|
99
|
+
});
|
|
100
|
+
var litellmPermissions = [
|
|
101
|
+
litellmKeyCreatePermission,
|
|
102
|
+
litellmKeyRevokePermission,
|
|
103
|
+
litellmKeyManagePermission,
|
|
104
|
+
litellmKeyResetSpendPermission,
|
|
105
|
+
litellmKeyUnblockPermission,
|
|
106
|
+
litellmAuditReadPermission,
|
|
107
|
+
litellmTeamCreatePermission,
|
|
108
|
+
litellmTeamManagePermission,
|
|
109
|
+
litellmTeamMembersManagePermission,
|
|
110
|
+
litellmTeamKnowledgebaseManagePermission,
|
|
111
|
+
litellmTeamMcpManagePermission,
|
|
112
|
+
litellmTeamDeletePermission
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
// src/keySchemas.ts
|
|
116
|
+
var import_zod = require("zod");
|
|
117
|
+
var RESERVED_METADATA_KEYS = ["blocked_by", "blocked_at"];
|
|
118
|
+
var RESERVED_METADATA_PREFIXES = ["created_", "updated_"];
|
|
119
|
+
function reservedMetadataKeys(metadata) {
|
|
120
|
+
return Object.keys(metadata).filter(
|
|
121
|
+
(k) => RESERVED_METADATA_KEYS.includes(k) || RESERVED_METADATA_PREFIXES.some((p) => k.startsWith(p))
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
function createGenerateKeyInputSchema(config) {
|
|
125
|
+
const durationSchema = config.allowedDurations.length > 0 ? import_zod.z.string().refine(
|
|
126
|
+
(val) => config.allowedDurations.includes(val),
|
|
127
|
+
{
|
|
128
|
+
message: `duration must be one of: ${config.allowedDurations.join(", ")}`
|
|
129
|
+
}
|
|
130
|
+
) : import_zod.z.string().regex(/^\d+[smhdwy]$/, {
|
|
131
|
+
message: 'duration must match format <number><unit> (e.g. "30d", "1h")'
|
|
132
|
+
});
|
|
133
|
+
return import_zod.z.object({
|
|
134
|
+
alias: import_zod.z.string().trim().min(1, "alias is required").max(128, "alias must be at most 128 characters"),
|
|
135
|
+
models: import_zod.z.array(import_zod.z.string()).max(100, "models array is too large").optional(),
|
|
136
|
+
duration: durationSchema.optional(),
|
|
137
|
+
max_budget: import_zod.z.number().positive("max_budget must be a positive number").max(config.maxBudget, `max_budget must not exceed ${config.maxBudget}`).nullable().optional(),
|
|
138
|
+
tpm_limit: import_zod.z.number().int("tpm_limit must be an integer").positive("tpm_limit must be a positive number").max(config.maxTpm, `tpm_limit must not exceed ${config.maxTpm}`).optional(),
|
|
139
|
+
rpm_limit: import_zod.z.number().int("rpm_limit must be an integer").positive("rpm_limit must be a positive number").max(config.maxRpm, `rpm_limit must not exceed ${config.maxRpm}`).optional(),
|
|
140
|
+
team_id: import_zod.z.string().optional(),
|
|
141
|
+
// The UI always sends 'llm_api'; no other key type may be requested.
|
|
142
|
+
key_type: import_zod.z.literal("llm_api").optional(),
|
|
143
|
+
metadata: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).refine((m) => reservedMetadataKeys(m).length === 0, {
|
|
144
|
+
message: "metadata may not set server-owned keys (blocked_by, blocked_at, created_*, updated_*)"
|
|
145
|
+
}).optional()
|
|
146
|
+
}).strict();
|
|
147
|
+
}
|
|
148
|
+
function createUpdateKeyInputSchema(config) {
|
|
149
|
+
return import_zod.z.object({
|
|
150
|
+
key_alias: import_zod.z.string().trim().min(1, "key_alias is required").max(128, "key_alias must be at most 128 characters").optional(),
|
|
151
|
+
models: import_zod.z.array(import_zod.z.string()).max(100, "models array is too large").optional(),
|
|
152
|
+
max_budget: import_zod.z.number().positive("max_budget must be a positive number").max(config.maxBudget, `max_budget must not exceed ${config.maxBudget}`).nullable().optional(),
|
|
153
|
+
tpm_limit: import_zod.z.number().int("tpm_limit must be an integer").positive("tpm_limit must be a positive number").max(config.maxTpm, `tpm_limit must not exceed ${config.maxTpm}`).optional(),
|
|
154
|
+
rpm_limit: import_zod.z.number().int("rpm_limit must be an integer").positive("rpm_limit must be a positive number").max(config.maxRpm, `rpm_limit must not exceed ${config.maxRpm}`).optional()
|
|
155
|
+
}).strict();
|
|
156
|
+
}
|
|
157
|
+
var DEFAULT_KEY_DURATIONS = ["1d", "7d", "30d", "90d"];
|
|
158
|
+
|
|
159
|
+
// src/budgets.ts
|
|
160
|
+
var BUDGET_WARNING_PCT = 80;
|
|
161
|
+
var BUDGET_DANGER_PCT = 100;
|
|
162
|
+
function budgetStatusForPct(pct) {
|
|
163
|
+
if (pct >= BUDGET_DANGER_PCT) return "over";
|
|
164
|
+
if (pct >= BUDGET_WARNING_PCT) return "near";
|
|
165
|
+
return "ok";
|
|
166
|
+
}
|
|
167
|
+
function formatDurationLabel(duration) {
|
|
168
|
+
const match = /^(\d+)([smhdwy])$/.exec(duration);
|
|
169
|
+
if (!match) return duration;
|
|
170
|
+
const [, num, unit] = match;
|
|
171
|
+
const n = Number(num);
|
|
172
|
+
const unitLabels = {
|
|
173
|
+
s: "Second",
|
|
174
|
+
m: "Minute",
|
|
175
|
+
h: "Hour",
|
|
176
|
+
d: "Day",
|
|
177
|
+
w: "Week",
|
|
178
|
+
y: "Year"
|
|
179
|
+
};
|
|
180
|
+
const label = unitLabels[unit] || unit;
|
|
181
|
+
return n === 1 ? `1 ${label}` : `${n} ${label}s`;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/modelAccess.ts
|
|
185
|
+
var ALL_PROXY_MODELS = "all-proxy-models";
|
|
186
|
+
function isModelAllowed(model, allowed) {
|
|
187
|
+
if (!allowed || allowed.length === 0) return true;
|
|
188
|
+
if (allowed.includes(ALL_PROXY_MODELS)) return true;
|
|
189
|
+
if (allowed.includes(model.model_name)) return true;
|
|
190
|
+
return !!model.access_groups?.some((group) => allowed.includes(group));
|
|
191
|
+
}
|
|
192
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
193
|
+
0 && (module.exports = {
|
|
194
|
+
ALL_PROXY_MODELS,
|
|
195
|
+
BUDGET_DANGER_PCT,
|
|
196
|
+
BUDGET_WARNING_PCT,
|
|
197
|
+
DEFAULT_KEY_DURATIONS,
|
|
198
|
+
RESERVED_METADATA_KEYS,
|
|
199
|
+
budgetStatusForPct,
|
|
200
|
+
createGenerateKeyInputSchema,
|
|
201
|
+
createUpdateKeyInputSchema,
|
|
202
|
+
formatDurationLabel,
|
|
203
|
+
isModelAllowed,
|
|
204
|
+
litellmAuditReadPermission,
|
|
205
|
+
litellmKeyCreatePermission,
|
|
206
|
+
litellmKeyManagePermission,
|
|
207
|
+
litellmKeyResetSpendPermission,
|
|
208
|
+
litellmKeyRevokePermission,
|
|
209
|
+
litellmKeyUnblockPermission,
|
|
210
|
+
litellmPermissions,
|
|
211
|
+
litellmTeamCreatePermission,
|
|
212
|
+
litellmTeamDeletePermission,
|
|
213
|
+
litellmTeamKnowledgebaseManagePermission,
|
|
214
|
+
litellmTeamManagePermission,
|
|
215
|
+
litellmTeamMcpManagePermission,
|
|
216
|
+
litellmTeamMembersManagePermission,
|
|
217
|
+
reservedMetadataKeys
|
|
218
|
+
});
|
|
219
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts", "../src/permissions.ts", "../src/keySchemas.ts", "../src/budgets.ts", "../src/modelAccess.ts"],
|
|
4
|
+
"sourcesContent": ["export * from './permissions';\nexport * from './keySchemas';\nexport * from './types';\nexport * from './budgets';\nexport * from './modelAccess';\n", "import { createPermission } from '@backstage/plugin-permission-common';\n\nexport const litellmKeyCreatePermission = createPermission({\n name: 'litellm.key.create',\n attributes: { action: 'create' },\n});\n\nexport const litellmKeyRevokePermission = createPermission({\n name: 'litellm.key.revoke',\n attributes: { action: 'delete' },\n});\n\nexport const litellmKeyManagePermission = createPermission({\n name: 'litellm.key.manage',\n attributes: { action: 'update' },\n});\n\nexport const litellmKeyResetSpendPermission = createPermission({\n name: 'litellm.key.resetSpend',\n attributes: { action: 'update' },\n});\n\nexport const litellmKeyUnblockPermission = createPermission({\n name: 'litellm.key.unblock',\n attributes: { action: 'update' },\n});\n\nexport const litellmAuditReadPermission = createPermission({\n name: 'litellm.audit.read',\n attributes: { action: 'read' },\n});\n\n// Team-management permissions \u2014 delegated to litellm-team-admins group\nexport const litellmTeamCreatePermission = createPermission({\n name: 'litellm.team.create',\n attributes: { action: 'create' },\n});\n\nexport const litellmTeamManagePermission = createPermission({\n name: 'litellm.team.manage',\n attributes: { action: 'update' },\n});\n\nexport const litellmTeamMembersManagePermission = createPermission({\n name: 'litellm.team.members.manage',\n attributes: { action: 'update' },\n});\n\nexport const litellmTeamKnowledgebaseManagePermission = createPermission({\n name: 'litellm.team.knowledgebase.manage',\n attributes: { action: 'update' },\n});\n\nexport const litellmTeamMcpManagePermission = createPermission({\n name: 'litellm.team.mcp.manage',\n attributes: { action: 'update' },\n});\n\nexport const litellmTeamDeletePermission = createPermission({\n name: 'litellm.team.delete',\n attributes: { action: 'delete' },\n});\n\nexport const litellmPermissions = [\n litellmKeyCreatePermission,\n litellmKeyRevokePermission,\n litellmKeyManagePermission,\n litellmKeyResetSpendPermission,\n litellmKeyUnblockPermission,\n litellmAuditReadPermission,\n litellmTeamCreatePermission,\n litellmTeamManagePermission,\n litellmTeamMembersManagePermission,\n litellmTeamKnowledgebaseManagePermission,\n litellmTeamMcpManagePermission,\n litellmTeamDeletePermission,\n];\n", "import { z } from 'zod';\n\n/**\n * Configuration for key validation ceilings and allowed values.\n */\n/**\n * Metadata keys the server owns. Clients must not set them: `blocked_by` /\n * `blocked_at` decide who may unblock a key, and `created_*` / `updated_*`\n * record provenance.\n */\nexport const RESERVED_METADATA_KEYS = ['blocked_by', 'blocked_at'] as const;\nconst RESERVED_METADATA_PREFIXES = ['created_', 'updated_'] as const;\n\nexport function reservedMetadataKeys(metadata: Record<string, unknown>): string[] {\n return Object.keys(metadata).filter(\n k =>\n (RESERVED_METADATA_KEYS as readonly string[]).includes(k) ||\n RESERVED_METADATA_PREFIXES.some(p => k.startsWith(p)),\n );\n}\n\nexport interface KeyValidationConfig {\n maxBudget: number;\n maxTpm: number;\n maxRpm: number;\n allowedDurations: string[];\n}\n\n/**\n * Creates a strict Zod schema for GenerateKeyInput validation.\n * Rejects unknown fields and enforces server-side ceilings.\n *\n * @param config Server configuration with ceiling values and allowed durations\n * @returns A Zod object schema that validates the input\n */\nexport function createGenerateKeyInputSchema(config: KeyValidationConfig) {\n // When allowedDurations is set, restrict to that list.\n // Otherwise, allow any string matching the duration format regex.\n const durationSchema = config.allowedDurations.length > 0\n ? z.string().refine(\n (val) => config.allowedDurations.includes(val),\n {\n message: `duration must be one of: ${config.allowedDurations.join(', ')}`,\n },\n )\n : z.string().regex(/^\\d+[smhdwy]$/, {\n message: 'duration must match format <number><unit> (e.g. \"30d\", \"1h\")',\n });\n\n return z\n .object({\n alias: z\n .string()\n .trim()\n .min(1, 'alias is required')\n .max(128, 'alias must be at most 128 characters'),\n models: z\n .array(z.string())\n .max(100, 'models array is too large')\n .optional(),\n duration: durationSchema.optional(),\n max_budget: z\n .number()\n .positive('max_budget must be a positive number')\n .max(config.maxBudget, `max_budget must not exceed ${config.maxBudget}`)\n .nullable()\n .optional(),\n tpm_limit: z\n .number()\n .int('tpm_limit must be an integer')\n .positive('tpm_limit must be a positive number')\n .max(config.maxTpm, `tpm_limit must not exceed ${config.maxTpm}`)\n .optional(),\n rpm_limit: z\n .number()\n .int('rpm_limit must be an integer')\n .positive('rpm_limit must be a positive number')\n .max(config.maxRpm, `rpm_limit must not exceed ${config.maxRpm}`)\n .optional(),\n team_id: z.string().optional(),\n // The UI always sends 'llm_api'; no other key type may be requested.\n key_type: z.literal('llm_api').optional(),\n metadata: z\n .record(z.string(), z.string())\n .refine(m => reservedMetadataKeys(m).length === 0, {\n message:\n 'metadata may not set server-owned keys (blocked_by, blocked_at, created_*, updated_*)',\n })\n .optional(),\n })\n .strict();\n}\n\nexport type GenerateKeyInput = z.infer<\n ReturnType<typeof createGenerateKeyInputSchema>\n>;\n\n/**\n * Creates a strict Zod schema for UpdateKeyInput validation.\n * Only allows key_alias, models, max_budget, tpm_limit, and rpm_limit fields.\n * Rejects all other fields including team_id, user_id, spend, blocked, key, and budget_duration.\n *\n * @param config Server configuration with ceiling values\n * @returns A Zod object schema that validates the input\n */\nexport function createUpdateKeyInputSchema(config: KeyValidationConfig) {\n return z\n .object({\n key_alias: z\n .string()\n .trim()\n .min(1, 'key_alias is required')\n .max(128, 'key_alias must be at most 128 characters')\n .optional(),\n models: z\n .array(z.string())\n .max(100, 'models array is too large')\n .optional(),\n max_budget: z\n .number()\n .positive('max_budget must be a positive number')\n .max(config.maxBudget, `max_budget must not exceed ${config.maxBudget}`)\n .nullable()\n .optional(),\n tpm_limit: z\n .number()\n .int('tpm_limit must be an integer')\n .positive('tpm_limit must be a positive number')\n .max(config.maxTpm, `tpm_limit must not exceed ${config.maxTpm}`)\n .optional(),\n rpm_limit: z\n .number()\n .int('rpm_limit must be an integer')\n .positive('rpm_limit must be a positive number')\n .max(config.maxRpm, `rpm_limit must not exceed ${config.maxRpm}`)\n .optional(),\n })\n .strict();\n}\n\nexport type UpdateKeyInput = z.infer<\n ReturnType<typeof createUpdateKeyInputSchema>\n>;\n\n/**\n * Default key duration presets. Used as server-side defaults and UI options.\n */\nexport const DEFAULT_KEY_DURATIONS = ['1d', '7d', '30d', '90d'];\n", "/** Budget warning threshold (percent of cap). */\nexport const BUDGET_WARNING_PCT = 80;\n\n/** Budget danger threshold (percent of cap, at or over cap). */\nexport const BUDGET_DANGER_PCT = 100;\n\n/** Consumption status derived from spend vs. cap. */\nexport type BudgetStatus = 'ok' | 'near' | 'over';\n\n/**\n * Compute budget status from spend percentage of cap.\n * Thresholds: near >= 80%, over >= 100%.\n */\nexport function budgetStatusForPct(pct: number): BudgetStatus {\n if (pct >= BUDGET_DANGER_PCT) return 'over';\n if (pct >= BUDGET_WARNING_PCT) return 'near';\n return 'ok';\n}\n\n/**\n * Format a duration string to a human-readable label.\n * E.g., \"1d\" \u2192 \"1 Day\", \"7d\" \u2192 \"7 Days\".\n */\nexport function formatDurationLabel(duration: string): string {\n const match = /^(\\d+)([smhdwy])$/.exec(duration);\n if (!match) return duration;\n\n const [, num, unit] = match;\n const n = Number(num);\n\n const unitLabels: Record<string, string> = {\n s: 'Second',\n m: 'Minute',\n h: 'Hour',\n d: 'Day',\n w: 'Week',\n y: 'Year',\n };\n\n const label = unitLabels[unit] || unit;\n return n === 1 ? `1 ${label}` : `${n} ${label}s`;\n}\n", "/**\n * LiteLLM sentinel: a team's (or user's) `models` list is `[\"all-proxy-models\"]`\n * when it isn't restricted to specific models.\n */\nexport const ALL_PROXY_MODELS = 'all-proxy-models';\n\n/**\n * Whether a model is allowed by an allow-list. The list is unrestricted when it\n * is empty/missing or contains the `all-proxy-models` sentinel. Entries may be\n * literal model names OR access-group names (litellm model_info.access_groups),\n * so a model also passes when one of its access groups is listed.\n */\nexport function isModelAllowed(\n model: { model_name: string; access_groups?: string[] },\n allowed?: string[],\n): boolean {\n if (!allowed || allowed.length === 0) return true;\n if (allowed.includes(ALL_PROXY_MODELS)) return true;\n if (allowed.includes(model.model_name)) return true;\n return !!model.access_groups?.some(group => allowed.includes(group));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./permissions"), exports);
|
|
18
|
+
__exportStar(require("./keySchemas"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
20
|
+
__exportStar(require("./budgets"), exports);
|
|
21
|
+
__exportStar(require("./modelAccess"), exports);
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for key validation ceilings and allowed values.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Metadata keys the server owns. Clients must not set them: `blocked_by` /
|
|
7
|
+
* `blocked_at` decide who may unblock a key, and `created_*` / `updated_*`
|
|
8
|
+
* record provenance.
|
|
9
|
+
*/
|
|
10
|
+
export declare const RESERVED_METADATA_KEYS: readonly ["blocked_by", "blocked_at"];
|
|
11
|
+
export declare function reservedMetadataKeys(metadata: Record<string, unknown>): string[];
|
|
12
|
+
export interface KeyValidationConfig {
|
|
13
|
+
maxBudget: number;
|
|
14
|
+
maxTpm: number;
|
|
15
|
+
maxRpm: number;
|
|
16
|
+
allowedDurations: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a strict Zod schema for GenerateKeyInput validation.
|
|
20
|
+
* Rejects unknown fields and enforces server-side ceilings.
|
|
21
|
+
*
|
|
22
|
+
* @param config Server configuration with ceiling values and allowed durations
|
|
23
|
+
* @returns A Zod object schema that validates the input
|
|
24
|
+
*/
|
|
25
|
+
export declare function createGenerateKeyInputSchema(config: KeyValidationConfig): z.ZodObject<{
|
|
26
|
+
alias: z.ZodString;
|
|
27
|
+
models: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
28
|
+
duration: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>> | z.ZodOptional<z.ZodString>;
|
|
29
|
+
max_budget: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
30
|
+
tpm_limit: z.ZodOptional<z.ZodNumber>;
|
|
31
|
+
rpm_limit: z.ZodOptional<z.ZodNumber>;
|
|
32
|
+
team_id: z.ZodOptional<z.ZodString>;
|
|
33
|
+
key_type: z.ZodOptional<z.ZodLiteral<"llm_api">>;
|
|
34
|
+
metadata: z.ZodOptional<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodString>, Record<string, string>, Record<string, string>>>;
|
|
35
|
+
}, "strict", z.ZodTypeAny, {
|
|
36
|
+
alias: string;
|
|
37
|
+
models?: string[] | undefined;
|
|
38
|
+
duration?: string | undefined;
|
|
39
|
+
max_budget?: number | null | undefined;
|
|
40
|
+
tpm_limit?: number | undefined;
|
|
41
|
+
rpm_limit?: number | undefined;
|
|
42
|
+
team_id?: string | undefined;
|
|
43
|
+
key_type?: "llm_api" | undefined;
|
|
44
|
+
metadata?: Record<string, string> | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
alias: string;
|
|
47
|
+
models?: string[] | undefined;
|
|
48
|
+
duration?: string | undefined;
|
|
49
|
+
max_budget?: number | null | undefined;
|
|
50
|
+
tpm_limit?: number | undefined;
|
|
51
|
+
rpm_limit?: number | undefined;
|
|
52
|
+
team_id?: string | undefined;
|
|
53
|
+
key_type?: "llm_api" | undefined;
|
|
54
|
+
metadata?: Record<string, string> | undefined;
|
|
55
|
+
}>;
|
|
56
|
+
export type GenerateKeyInput = z.infer<ReturnType<typeof createGenerateKeyInputSchema>>;
|
|
57
|
+
/**
|
|
58
|
+
* Creates a strict Zod schema for UpdateKeyInput validation.
|
|
59
|
+
* Only allows key_alias, models, max_budget, tpm_limit, and rpm_limit fields.
|
|
60
|
+
* Rejects all other fields including team_id, user_id, spend, blocked, key, and budget_duration.
|
|
61
|
+
*
|
|
62
|
+
* @param config Server configuration with ceiling values
|
|
63
|
+
* @returns A Zod object schema that validates the input
|
|
64
|
+
*/
|
|
65
|
+
export declare function createUpdateKeyInputSchema(config: KeyValidationConfig): z.ZodObject<{
|
|
66
|
+
key_alias: z.ZodOptional<z.ZodString>;
|
|
67
|
+
models: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
68
|
+
max_budget: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
69
|
+
tpm_limit: z.ZodOptional<z.ZodNumber>;
|
|
70
|
+
rpm_limit: z.ZodOptional<z.ZodNumber>;
|
|
71
|
+
}, "strict", z.ZodTypeAny, {
|
|
72
|
+
models?: string[] | undefined;
|
|
73
|
+
max_budget?: number | null | undefined;
|
|
74
|
+
tpm_limit?: number | undefined;
|
|
75
|
+
rpm_limit?: number | undefined;
|
|
76
|
+
key_alias?: string | undefined;
|
|
77
|
+
}, {
|
|
78
|
+
models?: string[] | undefined;
|
|
79
|
+
max_budget?: number | null | undefined;
|
|
80
|
+
tpm_limit?: number | undefined;
|
|
81
|
+
rpm_limit?: number | undefined;
|
|
82
|
+
key_alias?: string | undefined;
|
|
83
|
+
}>;
|
|
84
|
+
export type UpdateKeyInput = z.infer<ReturnType<typeof createUpdateKeyInputSchema>>;
|
|
85
|
+
/**
|
|
86
|
+
* Default key duration presets. Used as server-side defaults and UI options.
|
|
87
|
+
*/
|
|
88
|
+
export declare const DEFAULT_KEY_DURATIONS: string[];
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_KEY_DURATIONS = exports.RESERVED_METADATA_KEYS = void 0;
|
|
4
|
+
exports.reservedMetadataKeys = reservedMetadataKeys;
|
|
5
|
+
exports.createGenerateKeyInputSchema = createGenerateKeyInputSchema;
|
|
6
|
+
exports.createUpdateKeyInputSchema = createUpdateKeyInputSchema;
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for key validation ceilings and allowed values.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Metadata keys the server owns. Clients must not set them: `blocked_by` /
|
|
13
|
+
* `blocked_at` decide who may unblock a key, and `created_*` / `updated_*`
|
|
14
|
+
* record provenance.
|
|
15
|
+
*/
|
|
16
|
+
exports.RESERVED_METADATA_KEYS = ['blocked_by', 'blocked_at'];
|
|
17
|
+
const RESERVED_METADATA_PREFIXES = ['created_', 'updated_'];
|
|
18
|
+
function reservedMetadataKeys(metadata) {
|
|
19
|
+
return Object.keys(metadata).filter(k => exports.RESERVED_METADATA_KEYS.includes(k) ||
|
|
20
|
+
RESERVED_METADATA_PREFIXES.some(p => k.startsWith(p)));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a strict Zod schema for GenerateKeyInput validation.
|
|
24
|
+
* Rejects unknown fields and enforces server-side ceilings.
|
|
25
|
+
*
|
|
26
|
+
* @param config Server configuration with ceiling values and allowed durations
|
|
27
|
+
* @returns A Zod object schema that validates the input
|
|
28
|
+
*/
|
|
29
|
+
function createGenerateKeyInputSchema(config) {
|
|
30
|
+
// When allowedDurations is set, restrict to that list.
|
|
31
|
+
// Otherwise, allow any string matching the duration format regex.
|
|
32
|
+
const durationSchema = config.allowedDurations.length > 0
|
|
33
|
+
? zod_1.z.string().refine((val) => config.allowedDurations.includes(val), {
|
|
34
|
+
message: `duration must be one of: ${config.allowedDurations.join(', ')}`,
|
|
35
|
+
})
|
|
36
|
+
: zod_1.z.string().regex(/^\d+[smhdwy]$/, {
|
|
37
|
+
message: 'duration must match format <number><unit> (e.g. "30d", "1h")',
|
|
38
|
+
});
|
|
39
|
+
return zod_1.z
|
|
40
|
+
.object({
|
|
41
|
+
alias: zod_1.z
|
|
42
|
+
.string()
|
|
43
|
+
.trim()
|
|
44
|
+
.min(1, 'alias is required')
|
|
45
|
+
.max(128, 'alias must be at most 128 characters'),
|
|
46
|
+
models: zod_1.z
|
|
47
|
+
.array(zod_1.z.string())
|
|
48
|
+
.max(100, 'models array is too large')
|
|
49
|
+
.optional(),
|
|
50
|
+
duration: durationSchema.optional(),
|
|
51
|
+
max_budget: zod_1.z
|
|
52
|
+
.number()
|
|
53
|
+
.positive('max_budget must be a positive number')
|
|
54
|
+
.max(config.maxBudget, `max_budget must not exceed ${config.maxBudget}`)
|
|
55
|
+
.nullable()
|
|
56
|
+
.optional(),
|
|
57
|
+
tpm_limit: zod_1.z
|
|
58
|
+
.number()
|
|
59
|
+
.int('tpm_limit must be an integer')
|
|
60
|
+
.positive('tpm_limit must be a positive number')
|
|
61
|
+
.max(config.maxTpm, `tpm_limit must not exceed ${config.maxTpm}`)
|
|
62
|
+
.optional(),
|
|
63
|
+
rpm_limit: zod_1.z
|
|
64
|
+
.number()
|
|
65
|
+
.int('rpm_limit must be an integer')
|
|
66
|
+
.positive('rpm_limit must be a positive number')
|
|
67
|
+
.max(config.maxRpm, `rpm_limit must not exceed ${config.maxRpm}`)
|
|
68
|
+
.optional(),
|
|
69
|
+
team_id: zod_1.z.string().optional(),
|
|
70
|
+
// The UI always sends 'llm_api'; no other key type may be requested.
|
|
71
|
+
key_type: zod_1.z.literal('llm_api').optional(),
|
|
72
|
+
metadata: zod_1.z
|
|
73
|
+
.record(zod_1.z.string(), zod_1.z.string())
|
|
74
|
+
.refine(m => reservedMetadataKeys(m).length === 0, {
|
|
75
|
+
message: 'metadata may not set server-owned keys (blocked_by, blocked_at, created_*, updated_*)',
|
|
76
|
+
})
|
|
77
|
+
.optional(),
|
|
78
|
+
})
|
|
79
|
+
.strict();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates a strict Zod schema for UpdateKeyInput validation.
|
|
83
|
+
* Only allows key_alias, models, max_budget, tpm_limit, and rpm_limit fields.
|
|
84
|
+
* Rejects all other fields including team_id, user_id, spend, blocked, key, and budget_duration.
|
|
85
|
+
*
|
|
86
|
+
* @param config Server configuration with ceiling values
|
|
87
|
+
* @returns A Zod object schema that validates the input
|
|
88
|
+
*/
|
|
89
|
+
function createUpdateKeyInputSchema(config) {
|
|
90
|
+
return zod_1.z
|
|
91
|
+
.object({
|
|
92
|
+
key_alias: zod_1.z
|
|
93
|
+
.string()
|
|
94
|
+
.trim()
|
|
95
|
+
.min(1, 'key_alias is required')
|
|
96
|
+
.max(128, 'key_alias must be at most 128 characters')
|
|
97
|
+
.optional(),
|
|
98
|
+
models: zod_1.z
|
|
99
|
+
.array(zod_1.z.string())
|
|
100
|
+
.max(100, 'models array is too large')
|
|
101
|
+
.optional(),
|
|
102
|
+
max_budget: zod_1.z
|
|
103
|
+
.number()
|
|
104
|
+
.positive('max_budget must be a positive number')
|
|
105
|
+
.max(config.maxBudget, `max_budget must not exceed ${config.maxBudget}`)
|
|
106
|
+
.nullable()
|
|
107
|
+
.optional(),
|
|
108
|
+
tpm_limit: zod_1.z
|
|
109
|
+
.number()
|
|
110
|
+
.int('tpm_limit must be an integer')
|
|
111
|
+
.positive('tpm_limit must be a positive number')
|
|
112
|
+
.max(config.maxTpm, `tpm_limit must not exceed ${config.maxTpm}`)
|
|
113
|
+
.optional(),
|
|
114
|
+
rpm_limit: zod_1.z
|
|
115
|
+
.number()
|
|
116
|
+
.int('rpm_limit must be an integer')
|
|
117
|
+
.positive('rpm_limit must be a positive number')
|
|
118
|
+
.max(config.maxRpm, `rpm_limit must not exceed ${config.maxRpm}`)
|
|
119
|
+
.optional(),
|
|
120
|
+
})
|
|
121
|
+
.strict();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Default key duration presets. Used as server-side defaults and UI options.
|
|
125
|
+
*/
|
|
126
|
+
exports.DEFAULT_KEY_DURATIONS = ['1d', '7d', '30d', '90d'];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LiteLLM sentinel: a team's (or user's) `models` list is `["all-proxy-models"]`
|
|
3
|
+
* when it isn't restricted to specific models.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ALL_PROXY_MODELS = "all-proxy-models";
|
|
6
|
+
/**
|
|
7
|
+
* Whether a model is allowed by an allow-list. The list is unrestricted when it
|
|
8
|
+
* is empty/missing or contains the `all-proxy-models` sentinel. Entries may be
|
|
9
|
+
* literal model names OR access-group names (litellm model_info.access_groups),
|
|
10
|
+
* so a model also passes when one of its access groups is listed.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isModelAllowed(model: {
|
|
13
|
+
model_name: string;
|
|
14
|
+
access_groups?: string[];
|
|
15
|
+
}, allowed?: string[]): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ALL_PROXY_MODELS = void 0;
|
|
4
|
+
exports.isModelAllowed = isModelAllowed;
|
|
5
|
+
/**
|
|
6
|
+
* LiteLLM sentinel: a team's (or user's) `models` list is `["all-proxy-models"]`
|
|
7
|
+
* when it isn't restricted to specific models.
|
|
8
|
+
*/
|
|
9
|
+
exports.ALL_PROXY_MODELS = 'all-proxy-models';
|
|
10
|
+
/**
|
|
11
|
+
* Whether a model is allowed by an allow-list. The list is unrestricted when it
|
|
12
|
+
* is empty/missing or contains the `all-proxy-models` sentinel. Entries may be
|
|
13
|
+
* literal model names OR access-group names (litellm model_info.access_groups),
|
|
14
|
+
* so a model also passes when one of its access groups is listed.
|
|
15
|
+
*/
|
|
16
|
+
function isModelAllowed(model, allowed) {
|
|
17
|
+
if (!allowed || allowed.length === 0)
|
|
18
|
+
return true;
|
|
19
|
+
if (allowed.includes(exports.ALL_PROXY_MODELS))
|
|
20
|
+
return true;
|
|
21
|
+
if (allowed.includes(model.model_name))
|
|
22
|
+
return true;
|
|
23
|
+
return !!model.access_groups?.some(group => allowed.includes(group));
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const litellmKeyCreatePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
2
|
+
export declare const litellmKeyRevokePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
3
|
+
export declare const litellmKeyManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
4
|
+
export declare const litellmKeyResetSpendPermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
5
|
+
export declare const litellmKeyUnblockPermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
6
|
+
export declare const litellmAuditReadPermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
7
|
+
export declare const litellmTeamCreatePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
8
|
+
export declare const litellmTeamManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
9
|
+
export declare const litellmTeamMembersManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
10
|
+
export declare const litellmTeamKnowledgebaseManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
11
|
+
export declare const litellmTeamMcpManagePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
12
|
+
export declare const litellmTeamDeletePermission: import("@backstage/plugin-permission-common").BasicPermission;
|
|
13
|
+
export declare const litellmPermissions: import("@backstage/plugin-permission-common").BasicPermission[];
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.litellmPermissions = exports.litellmTeamDeletePermission = exports.litellmTeamMcpManagePermission = exports.litellmTeamKnowledgebaseManagePermission = exports.litellmTeamMembersManagePermission = exports.litellmTeamManagePermission = exports.litellmTeamCreatePermission = exports.litellmAuditReadPermission = exports.litellmKeyUnblockPermission = exports.litellmKeyResetSpendPermission = exports.litellmKeyManagePermission = exports.litellmKeyRevokePermission = exports.litellmKeyCreatePermission = void 0;
|
|
4
|
+
const plugin_permission_common_1 = require("@backstage/plugin-permission-common");
|
|
5
|
+
exports.litellmKeyCreatePermission = (0, plugin_permission_common_1.createPermission)({
|
|
6
|
+
name: 'litellm.key.create',
|
|
7
|
+
attributes: { action: 'create' },
|
|
8
|
+
});
|
|
9
|
+
exports.litellmKeyRevokePermission = (0, plugin_permission_common_1.createPermission)({
|
|
10
|
+
name: 'litellm.key.revoke',
|
|
11
|
+
attributes: { action: 'delete' },
|
|
12
|
+
});
|
|
13
|
+
exports.litellmKeyManagePermission = (0, plugin_permission_common_1.createPermission)({
|
|
14
|
+
name: 'litellm.key.manage',
|
|
15
|
+
attributes: { action: 'update' },
|
|
16
|
+
});
|
|
17
|
+
exports.litellmKeyResetSpendPermission = (0, plugin_permission_common_1.createPermission)({
|
|
18
|
+
name: 'litellm.key.resetSpend',
|
|
19
|
+
attributes: { action: 'update' },
|
|
20
|
+
});
|
|
21
|
+
exports.litellmKeyUnblockPermission = (0, plugin_permission_common_1.createPermission)({
|
|
22
|
+
name: 'litellm.key.unblock',
|
|
23
|
+
attributes: { action: 'update' },
|
|
24
|
+
});
|
|
25
|
+
exports.litellmAuditReadPermission = (0, plugin_permission_common_1.createPermission)({
|
|
26
|
+
name: 'litellm.audit.read',
|
|
27
|
+
attributes: { action: 'read' },
|
|
28
|
+
});
|
|
29
|
+
// Team-management permissions — delegated to litellm-team-admins group
|
|
30
|
+
exports.litellmTeamCreatePermission = (0, plugin_permission_common_1.createPermission)({
|
|
31
|
+
name: 'litellm.team.create',
|
|
32
|
+
attributes: { action: 'create' },
|
|
33
|
+
});
|
|
34
|
+
exports.litellmTeamManagePermission = (0, plugin_permission_common_1.createPermission)({
|
|
35
|
+
name: 'litellm.team.manage',
|
|
36
|
+
attributes: { action: 'update' },
|
|
37
|
+
});
|
|
38
|
+
exports.litellmTeamMembersManagePermission = (0, plugin_permission_common_1.createPermission)({
|
|
39
|
+
name: 'litellm.team.members.manage',
|
|
40
|
+
attributes: { action: 'update' },
|
|
41
|
+
});
|
|
42
|
+
exports.litellmTeamKnowledgebaseManagePermission = (0, plugin_permission_common_1.createPermission)({
|
|
43
|
+
name: 'litellm.team.knowledgebase.manage',
|
|
44
|
+
attributes: { action: 'update' },
|
|
45
|
+
});
|
|
46
|
+
exports.litellmTeamMcpManagePermission = (0, plugin_permission_common_1.createPermission)({
|
|
47
|
+
name: 'litellm.team.mcp.manage',
|
|
48
|
+
attributes: { action: 'update' },
|
|
49
|
+
});
|
|
50
|
+
exports.litellmTeamDeletePermission = (0, plugin_permission_common_1.createPermission)({
|
|
51
|
+
name: 'litellm.team.delete',
|
|
52
|
+
attributes: { action: 'delete' },
|
|
53
|
+
});
|
|
54
|
+
exports.litellmPermissions = [
|
|
55
|
+
exports.litellmKeyCreatePermission,
|
|
56
|
+
exports.litellmKeyRevokePermission,
|
|
57
|
+
exports.litellmKeyManagePermission,
|
|
58
|
+
exports.litellmKeyResetSpendPermission,
|
|
59
|
+
exports.litellmKeyUnblockPermission,
|
|
60
|
+
exports.litellmAuditReadPermission,
|
|
61
|
+
exports.litellmTeamCreatePermission,
|
|
62
|
+
exports.litellmTeamManagePermission,
|
|
63
|
+
exports.litellmTeamMembersManagePermission,
|
|
64
|
+
exports.litellmTeamKnowledgebaseManagePermission,
|
|
65
|
+
exports.litellmTeamMcpManagePermission,
|
|
66
|
+
exports.litellmTeamDeletePermission,
|
|
67
|
+
];
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
export interface UserInfo {
|
|
2
|
+
user_id: string;
|
|
3
|
+
user_email?: string;
|
|
4
|
+
email?: string;
|
|
5
|
+
teams?: string[];
|
|
6
|
+
models?: string[];
|
|
7
|
+
max_budget?: number;
|
|
8
|
+
spend?: number;
|
|
9
|
+
current_spend?: number;
|
|
10
|
+
soft_limit?: number;
|
|
11
|
+
hard_limit?: number;
|
|
12
|
+
/** Spend-reset period for max_budget, e.g. "30d". */
|
|
13
|
+
budget_duration?: string;
|
|
14
|
+
/** ISO timestamp when max_budget next resets (set when budget_duration is). */
|
|
15
|
+
budget_reset_at?: string;
|
|
16
|
+
/** Backstage-computed: true when the user is a member of litellm.audit.group */
|
|
17
|
+
can_view_audit?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface TeamMember {
|
|
20
|
+
user_id: string;
|
|
21
|
+
user_email?: string;
|
|
22
|
+
role: 'admin' | 'user';
|
|
23
|
+
}
|
|
24
|
+
export interface TeamObjectPermission {
|
|
25
|
+
/** Vector store ids/names attached to the team. */
|
|
26
|
+
vector_stores?: string[];
|
|
27
|
+
/** MCP server ids/names attached to the team. */
|
|
28
|
+
mcp_servers?: string[];
|
|
29
|
+
/** MCP access group names attached to the team. */
|
|
30
|
+
mcp_access_groups?: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface TeamInfo {
|
|
33
|
+
team_id: string;
|
|
34
|
+
team_alias?: string;
|
|
35
|
+
max_budget?: number;
|
|
36
|
+
/** Spend-reset period for max_budget, e.g. "30d". */
|
|
37
|
+
budget_duration?: string;
|
|
38
|
+
spend: number;
|
|
39
|
+
/**
|
|
40
|
+
* Share of max_budget consumed (0-100), present only on redacted records.
|
|
41
|
+
* Set by the backend when litellm.display.hideTeamBudgetFor* is enabled so
|
|
42
|
+
* clients can render the consumption level without dollar amounts.
|
|
43
|
+
*/
|
|
44
|
+
budget_pct?: number;
|
|
45
|
+
/** ok | near (>=80%) | over (>=100%), present only on redacted records. */
|
|
46
|
+
budget_status?: 'ok' | 'near' | 'over';
|
|
47
|
+
/** True when max_budget/spend were stripped by budget hiding. */
|
|
48
|
+
budget_hidden?: boolean;
|
|
49
|
+
members_with_roles?: TeamMember[];
|
|
50
|
+
models?: string[];
|
|
51
|
+
tpm_limit?: number;
|
|
52
|
+
rpm_limit?: number;
|
|
53
|
+
/** Arbitrary metadata stored on the team record. */
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
55
|
+
/** Knowledge bases (vector stores) and MCP servers attached to the team. */
|
|
56
|
+
object_permission?: TeamObjectPermission;
|
|
57
|
+
/** Whether the team is blocked/deactivated. */
|
|
58
|
+
blocked?: boolean;
|
|
59
|
+
/** Max budget available to individual team members (if set per-member). */
|
|
60
|
+
team_member_budget?: number;
|
|
61
|
+
}
|
|
62
|
+
export interface VirtualKey {
|
|
63
|
+
key: string;
|
|
64
|
+
token?: string;
|
|
65
|
+
key_alias?: string;
|
|
66
|
+
created_at: string;
|
|
67
|
+
expires_at?: string;
|
|
68
|
+
spend: number;
|
|
69
|
+
max_budget?: number;
|
|
70
|
+
budget_duration?: string;
|
|
71
|
+
tpm_limit?: number;
|
|
72
|
+
rpm_limit?: number;
|
|
73
|
+
models?: string[];
|
|
74
|
+
user_id?: string;
|
|
75
|
+
/** Team the key is bound to, when any (used to scope the model picker). */
|
|
76
|
+
team_id?: string;
|
|
77
|
+
blocked?: boolean;
|
|
78
|
+
/** Arbitrary metadata stored on the key record. */
|
|
79
|
+
metadata?: Record<string, unknown>;
|
|
80
|
+
}
|
|
81
|
+
export interface ModelInfo {
|
|
82
|
+
model_name: string;
|
|
83
|
+
mode: string;
|
|
84
|
+
supports_function_calling?: boolean;
|
|
85
|
+
supports_vision?: boolean;
|
|
86
|
+
input_cost_per_token?: number;
|
|
87
|
+
output_cost_per_token?: number;
|
|
88
|
+
max_input_tokens?: number;
|
|
89
|
+
max_output_tokens?: number;
|
|
90
|
+
/** Access group names this model belongs to (litellm.model_info.access_groups). A team's `models` list can reference a group name instead of a literal model_name. */
|
|
91
|
+
access_groups?: string[];
|
|
92
|
+
}
|
|
93
|
+
export interface UsageModelBreakdown {
|
|
94
|
+
total_spend: number;
|
|
95
|
+
total_tokens: number;
|
|
96
|
+
prompt_tokens: number;
|
|
97
|
+
completion_tokens: number;
|
|
98
|
+
api_requests: number;
|
|
99
|
+
successful_requests: number;
|
|
100
|
+
failed_requests: number;
|
|
101
|
+
}
|
|
102
|
+
export interface UsageKeyBreakdown {
|
|
103
|
+
key_alias?: string;
|
|
104
|
+
team_id?: string | null;
|
|
105
|
+
models: string[];
|
|
106
|
+
total_spend: number;
|
|
107
|
+
total_tokens: number;
|
|
108
|
+
prompt_tokens: number;
|
|
109
|
+
completion_tokens: number;
|
|
110
|
+
api_requests: number;
|
|
111
|
+
successful_requests: number;
|
|
112
|
+
failed_requests: number;
|
|
113
|
+
}
|
|
114
|
+
export interface UsageDailyPoint {
|
|
115
|
+
date: string;
|
|
116
|
+
spend: number;
|
|
117
|
+
total_tokens: number;
|
|
118
|
+
prompt_tokens: number;
|
|
119
|
+
completion_tokens: number;
|
|
120
|
+
api_requests: number;
|
|
121
|
+
successful_requests: number;
|
|
122
|
+
failed_requests: number;
|
|
123
|
+
}
|
|
124
|
+
export interface UsageDailyModelPoint {
|
|
125
|
+
date: string;
|
|
126
|
+
model: string;
|
|
127
|
+
spend: number;
|
|
128
|
+
prompt_tokens: number;
|
|
129
|
+
completion_tokens: number;
|
|
130
|
+
total_tokens: number;
|
|
131
|
+
api_requests: number;
|
|
132
|
+
successful_requests: number;
|
|
133
|
+
failed_requests: number;
|
|
134
|
+
}
|
|
135
|
+
export interface UsageMetrics {
|
|
136
|
+
total_spend: number;
|
|
137
|
+
total_tokens: number;
|
|
138
|
+
prompt_tokens: number;
|
|
139
|
+
completion_tokens: number;
|
|
140
|
+
api_requests: number;
|
|
141
|
+
successful_requests: number;
|
|
142
|
+
failed_requests: number;
|
|
143
|
+
usage_by_model: Record<string, UsageModelBreakdown>;
|
|
144
|
+
usage_by_key: Record<string, UsageKeyBreakdown>;
|
|
145
|
+
daily_usage: UsageDailyPoint[];
|
|
146
|
+
daily_by_model: UsageDailyModelPoint[];
|
|
147
|
+
}
|
|
148
|
+
export interface GenerateKeyRequest {
|
|
149
|
+
alias?: string;
|
|
150
|
+
models?: string[];
|
|
151
|
+
team_id?: string;
|
|
152
|
+
duration?: string;
|
|
153
|
+
/** Positive number caps spend; null/undefined means unlimited. */
|
|
154
|
+
max_budget?: number | null;
|
|
155
|
+
tpm_limit?: number;
|
|
156
|
+
rpm_limit?: number;
|
|
157
|
+
key_type?: string;
|
|
158
|
+
metadata?: Record<string, string>;
|
|
159
|
+
/** Backend-only: user ID for the key owner (set from authenticated principal). */
|
|
160
|
+
user_id?: string;
|
|
161
|
+
}
|
|
162
|
+
export interface UpdateKeyRequest {
|
|
163
|
+
key?: string;
|
|
164
|
+
key_alias?: string;
|
|
165
|
+
models?: string[];
|
|
166
|
+
/** Positive number caps spend; null clears it (unlimited, gated by allowUnlimitedBudget). */
|
|
167
|
+
max_budget?: number | null;
|
|
168
|
+
tpm_limit?: number;
|
|
169
|
+
rpm_limit?: number;
|
|
170
|
+
team_id?: string;
|
|
171
|
+
duration?: string;
|
|
172
|
+
/** Arbitrary metadata to merge with the existing record. */
|
|
173
|
+
metadata?: Record<string, unknown>;
|
|
174
|
+
}
|
|
175
|
+
export interface GenerateKeyResponse {
|
|
176
|
+
key: string;
|
|
177
|
+
key_alias?: string;
|
|
178
|
+
expires_at?: string;
|
|
179
|
+
max_budget?: number;
|
|
180
|
+
tpm_limit?: number;
|
|
181
|
+
rpm_limit?: number;
|
|
182
|
+
models?: string[];
|
|
183
|
+
}
|
|
184
|
+
export interface AuditLogEntry {
|
|
185
|
+
id: string;
|
|
186
|
+
updated_at: string;
|
|
187
|
+
changed_by?: string;
|
|
188
|
+
changed_by_api_key?: string;
|
|
189
|
+
action?: string;
|
|
190
|
+
table_name?: string;
|
|
191
|
+
object_id?: string;
|
|
192
|
+
before_value?: Record<string, unknown> | null;
|
|
193
|
+
updated_values?: Record<string, unknown> | null;
|
|
194
|
+
}
|
|
195
|
+
export interface PaginatedAuditLogs {
|
|
196
|
+
audit_logs: AuditLogEntry[];
|
|
197
|
+
total: number;
|
|
198
|
+
page: number;
|
|
199
|
+
page_size: number;
|
|
200
|
+
total_pages: number;
|
|
201
|
+
}
|
|
202
|
+
export interface AuditLogsParams {
|
|
203
|
+
page?: number;
|
|
204
|
+
page_size?: number;
|
|
205
|
+
start_date?: string;
|
|
206
|
+
end_date?: string;
|
|
207
|
+
action?: string;
|
|
208
|
+
table_name?: string;
|
|
209
|
+
changed_by?: string;
|
|
210
|
+
sort_by?: string;
|
|
211
|
+
sort_order?: 'asc' | 'desc';
|
|
212
|
+
}
|
|
213
|
+
export interface CreateTeamResponse {
|
|
214
|
+
team_id: string;
|
|
215
|
+
team_alias?: string;
|
|
216
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@acarmisc/backstage-plugin-litellm-common",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Shared types, permissions, and schemas for the LiteLLM Backstage plugin",
|
|
5
|
+
"backstage": {
|
|
6
|
+
"role": "common-library",
|
|
7
|
+
"pluginId": "litellm"
|
|
8
|
+
},
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/acarmisc/backstage-plugin-litellm-govai"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/acarmisc/backstage-plugin-litellm-govai#readme",
|
|
17
|
+
"license": "Apache-2.0",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.cjs.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"main": "dist/index.cjs.js",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "node build.js && tsc -p tsconfig.json",
|
|
31
|
+
"test": "tsc -p tsconfig.test.json && node --test \"dist-test/**/*.test.js\"",
|
|
32
|
+
"prepack": "npm run build",
|
|
33
|
+
"postpack": ""
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@backstage/plugin-permission-common": "^0.9.10",
|
|
37
|
+
"zod": "^3.22.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^20.0.0",
|
|
41
|
+
"esbuild": "^0.28.0",
|
|
42
|
+
"typescript": "^5.9.3"
|
|
43
|
+
}
|
|
44
|
+
}
|