@happyvertical/ai 0.74.8
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/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/README.md +384 -0
- package/dist/chunks/anthropic-BRwbhwIl.js +463 -0
- package/dist/chunks/anthropic-BRwbhwIl.js.map +1 -0
- package/dist/chunks/bedrock-Cf1xUerN.js +808 -0
- package/dist/chunks/bedrock-Cf1xUerN.js.map +1 -0
- package/dist/chunks/bifrost-3mXtQsTj.js +233 -0
- package/dist/chunks/bifrost-3mXtQsTj.js.map +1 -0
- package/dist/chunks/claude-cli-BrHRfkry.js +603 -0
- package/dist/chunks/claude-cli-BrHRfkry.js.map +1 -0
- package/dist/chunks/gateway-admin-C4GFPbZF.js +359 -0
- package/dist/chunks/gateway-admin-C4GFPbZF.js.map +1 -0
- package/dist/chunks/gemini-BfpHXDIQ.js +662 -0
- package/dist/chunks/gemini-BfpHXDIQ.js.map +1 -0
- package/dist/chunks/huggingface-280qv9iv.js +366 -0
- package/dist/chunks/huggingface-280qv9iv.js.map +1 -0
- package/dist/chunks/index-BT4thAvS.js +934 -0
- package/dist/chunks/index-BT4thAvS.js.map +1 -0
- package/dist/chunks/litellm-DhPKa_Jz.js +220 -0
- package/dist/chunks/litellm-DhPKa_Jz.js.map +1 -0
- package/dist/chunks/ollama-Di1ldur0.js +851 -0
- package/dist/chunks/ollama-Di1ldur0.js.map +1 -0
- package/dist/chunks/openai-5snI2diE.js +749 -0
- package/dist/chunks/openai-5snI2diE.js.map +1 -0
- package/dist/chunks/qwen-tts-DgPgdXxG.js +365 -0
- package/dist/chunks/qwen-tts-DgPgdXxG.js.map +1 -0
- package/dist/chunks/usage-DMWiJ2oB.js +21 -0
- package/dist/chunks/usage-DMWiJ2oB.js.map +1 -0
- package/dist/cli/claude-context.d.ts +3 -0
- package/dist/cli/claude-context.d.ts.map +1 -0
- package/dist/cli/claude-context.js +21 -0
- package/dist/cli/claude-context.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/node/factory.d.ts +27 -0
- package/dist/node/factory.d.ts.map +1 -0
- package/dist/shared/client.d.ts +410 -0
- package/dist/shared/client.d.ts.map +1 -0
- package/dist/shared/factory.d.ts +83 -0
- package/dist/shared/factory.d.ts.map +1 -0
- package/dist/shared/message.d.ts +71 -0
- package/dist/shared/message.d.ts.map +1 -0
- package/dist/shared/providers/anthropic.d.ts +82 -0
- package/dist/shared/providers/anthropic.d.ts.map +1 -0
- package/dist/shared/providers/bedrock.d.ts +49 -0
- package/dist/shared/providers/bedrock.d.ts.map +1 -0
- package/dist/shared/providers/bifrost.d.ts +25 -0
- package/dist/shared/providers/bifrost.d.ts.map +1 -0
- package/dist/shared/providers/claude-cli.d.ts +139 -0
- package/dist/shared/providers/claude-cli.d.ts.map +1 -0
- package/dist/shared/providers/gateway-admin.d.ts +35 -0
- package/dist/shared/providers/gateway-admin.d.ts.map +1 -0
- package/dist/shared/providers/gemini.d.ts +116 -0
- package/dist/shared/providers/gemini.d.ts.map +1 -0
- package/dist/shared/providers/huggingface.d.ts +33 -0
- package/dist/shared/providers/huggingface.d.ts.map +1 -0
- package/dist/shared/providers/litellm.d.ts +25 -0
- package/dist/shared/providers/litellm.d.ts.map +1 -0
- package/dist/shared/providers/ollama.d.ts +47 -0
- package/dist/shared/providers/ollama.d.ts.map +1 -0
- package/dist/shared/providers/openai.d.ts +272 -0
- package/dist/shared/providers/openai.d.ts.map +1 -0
- package/dist/shared/providers/qwen-tts.d.ts +85 -0
- package/dist/shared/providers/qwen-tts.d.ts.map +1 -0
- package/dist/shared/providers/usage.d.ts +14 -0
- package/dist/shared/providers/usage.d.ts.map +1 -0
- package/dist/shared/rate-limit.d.ts +13 -0
- package/dist/shared/rate-limit.d.ts.map +1 -0
- package/dist/shared/thread.d.ts +104 -0
- package/dist/shared/thread.d.ts.map +1 -0
- package/dist/shared/types.d.ts +1779 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/metadata.json +35 -0
- package/package.json +62 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import { A as AIError } from "./index-BT4thAvS.js";
|
|
2
|
+
function stripTrailingSlash(value) {
|
|
3
|
+
return value.endsWith("/") ? value.slice(0, -1) : value;
|
|
4
|
+
}
|
|
5
|
+
function normalizeGatewayBaseUrl(baseUrl) {
|
|
6
|
+
return stripTrailingSlash(baseUrl.trim());
|
|
7
|
+
}
|
|
8
|
+
function deriveGatewayAdminBaseUrl(baseUrl) {
|
|
9
|
+
let normalized = normalizeGatewayBaseUrl(baseUrl);
|
|
10
|
+
const suffixes = ["/pydanticai/v1", "/openai", "/v1"];
|
|
11
|
+
let stripped = true;
|
|
12
|
+
while (stripped) {
|
|
13
|
+
stripped = false;
|
|
14
|
+
for (const suffix of suffixes) {
|
|
15
|
+
if (normalized.endsWith(suffix)) {
|
|
16
|
+
normalized = normalized.slice(0, -suffix.length);
|
|
17
|
+
stripped = true;
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return normalized || normalizeGatewayBaseUrl(baseUrl);
|
|
23
|
+
}
|
|
24
|
+
function resolveGatewayAdminBaseUrl(baseUrl, adminBaseUrl, provider) {
|
|
25
|
+
const configuredBaseUrl = adminBaseUrl || baseUrl;
|
|
26
|
+
if (!configuredBaseUrl?.trim()) {
|
|
27
|
+
throw new AIError(
|
|
28
|
+
`${provider} baseUrl is required for admin operations`,
|
|
29
|
+
"ADMIN_BASE_URL_REQUIRED",
|
|
30
|
+
provider
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return adminBaseUrl ? normalizeGatewayBaseUrl(adminBaseUrl) : deriveGatewayAdminBaseUrl(configuredBaseUrl);
|
|
34
|
+
}
|
|
35
|
+
function slugifyProjectId(name, tenantId) {
|
|
36
|
+
const value = [tenantId, name].filter(Boolean).join("-");
|
|
37
|
+
const slug = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
38
|
+
return slug || "ai-project";
|
|
39
|
+
}
|
|
40
|
+
function toJsonRecord(value) {
|
|
41
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
42
|
+
}
|
|
43
|
+
function stringValue(value) {
|
|
44
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
45
|
+
}
|
|
46
|
+
function encodeBasicCredentials(username, password) {
|
|
47
|
+
const value = `${username}:${password}`;
|
|
48
|
+
if (typeof btoa === "function") {
|
|
49
|
+
return btoa(value);
|
|
50
|
+
}
|
|
51
|
+
return Buffer.from(value, "utf8").toString("base64");
|
|
52
|
+
}
|
|
53
|
+
function removeUndefinedValues(value) {
|
|
54
|
+
for (const key of Object.keys(value)) {
|
|
55
|
+
if (value[key] === void 0) {
|
|
56
|
+
delete value[key];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
function createMetadata(options, tenantField = "tenant_id") {
|
|
62
|
+
const metadata = {
|
|
63
|
+
...options.metadata
|
|
64
|
+
};
|
|
65
|
+
if (options.tenantId) {
|
|
66
|
+
metadata[tenantField] = options.tenantId;
|
|
67
|
+
}
|
|
68
|
+
if (options.description) {
|
|
69
|
+
metadata.description = options.description;
|
|
70
|
+
}
|
|
71
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
72
|
+
}
|
|
73
|
+
function responseMessage(body, fallback) {
|
|
74
|
+
const record = toJsonRecord(body);
|
|
75
|
+
const error = toJsonRecord(record.error);
|
|
76
|
+
return stringValue(error.message) || stringValue(record.message) || stringValue(record.detail) || fallback;
|
|
77
|
+
}
|
|
78
|
+
class GatewayAdminTransport {
|
|
79
|
+
baseUrl;
|
|
80
|
+
provider;
|
|
81
|
+
apiKey;
|
|
82
|
+
username;
|
|
83
|
+
password;
|
|
84
|
+
headers;
|
|
85
|
+
timeout;
|
|
86
|
+
constructor(options) {
|
|
87
|
+
this.provider = options.provider;
|
|
88
|
+
this.baseUrl = normalizeGatewayBaseUrl(options.baseUrl);
|
|
89
|
+
this.apiKey = options.apiKey;
|
|
90
|
+
this.username = options.username;
|
|
91
|
+
this.password = options.password;
|
|
92
|
+
this.headers = options.headers;
|
|
93
|
+
this.timeout = options.timeout;
|
|
94
|
+
}
|
|
95
|
+
async request(method, path, body, query) {
|
|
96
|
+
const url = new URL(
|
|
97
|
+
`${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`
|
|
98
|
+
);
|
|
99
|
+
if (query) {
|
|
100
|
+
for (const [key, value] of Object.entries(query)) {
|
|
101
|
+
if (value !== void 0) {
|
|
102
|
+
url.searchParams.set(key, value);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const controller = typeof AbortController === "undefined" ? void 0 : new AbortController();
|
|
107
|
+
const timeoutHandle = controller && this.timeout ? setTimeout(() => controller.abort(), this.timeout) : void 0;
|
|
108
|
+
try {
|
|
109
|
+
const response = await fetch(url, {
|
|
110
|
+
method,
|
|
111
|
+
headers: {
|
|
112
|
+
Accept: "application/json",
|
|
113
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
114
|
+
...this.headers,
|
|
115
|
+
...this.createAuthHeaders()
|
|
116
|
+
},
|
|
117
|
+
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
118
|
+
signal: controller?.signal
|
|
119
|
+
});
|
|
120
|
+
const text = await response.text();
|
|
121
|
+
const parsed = text ? this.parseJson(text) : void 0;
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw this.mapResponseError(response, parsed);
|
|
124
|
+
}
|
|
125
|
+
return parsed;
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (error instanceof AIError) {
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
throw new AIError(
|
|
131
|
+
`${this.provider} admin request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
132
|
+
"ADMIN_REQUEST_FAILED",
|
|
133
|
+
this.provider
|
|
134
|
+
);
|
|
135
|
+
} finally {
|
|
136
|
+
if (timeoutHandle) {
|
|
137
|
+
clearTimeout(timeoutHandle);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
createAuthHeaders() {
|
|
142
|
+
if (this.username && this.password) {
|
|
143
|
+
return {
|
|
144
|
+
Authorization: `Basic ${encodeBasicCredentials(
|
|
145
|
+
this.username,
|
|
146
|
+
this.password
|
|
147
|
+
)}`
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {};
|
|
151
|
+
}
|
|
152
|
+
parseJson(text) {
|
|
153
|
+
try {
|
|
154
|
+
return JSON.parse(text);
|
|
155
|
+
} catch (_error) {
|
|
156
|
+
return { message: text };
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
mapResponseError(response, body) {
|
|
160
|
+
const message = responseMessage(
|
|
161
|
+
body,
|
|
162
|
+
`${this.provider} admin request failed with ${response.status}`
|
|
163
|
+
);
|
|
164
|
+
if (response.status === 401 || response.status === 403) {
|
|
165
|
+
return new AIError(message, "AUTH_ERROR", this.provider);
|
|
166
|
+
}
|
|
167
|
+
if (response.status === 429) {
|
|
168
|
+
return new AIError(message, "RATE_LIMIT", this.provider, void 0, true);
|
|
169
|
+
}
|
|
170
|
+
return new AIError(
|
|
171
|
+
message,
|
|
172
|
+
`ADMIN_HTTP_${response.status}`,
|
|
173
|
+
this.provider,
|
|
174
|
+
void 0,
|
|
175
|
+
response.status >= 500
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function mapBifrostBudget(budget) {
|
|
180
|
+
if (!budget) return void 0;
|
|
181
|
+
return removeUndefinedValues({
|
|
182
|
+
max_limit: budget.maxLimit,
|
|
183
|
+
reset_duration: budget.resetDuration,
|
|
184
|
+
calendar_aligned: budget.calendarAligned
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function mapBifrostRateLimit(rateLimit) {
|
|
188
|
+
if (!rateLimit) return void 0;
|
|
189
|
+
return removeUndefinedValues({
|
|
190
|
+
token_max_limit: rateLimit.tokenMaxLimit ?? rateLimit.tpmLimit,
|
|
191
|
+
token_reset_duration: rateLimit.tokenResetDuration,
|
|
192
|
+
request_max_limit: rateLimit.requestMaxLimit ?? rateLimit.rpmLimit,
|
|
193
|
+
request_reset_duration: rateLimit.requestResetDuration
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
function mapBifrostProviderConfigs(configs) {
|
|
197
|
+
if (!configs) return void 0;
|
|
198
|
+
return configs.map(
|
|
199
|
+
(config) => removeUndefinedValues({
|
|
200
|
+
provider: config.provider,
|
|
201
|
+
weight: config.weight,
|
|
202
|
+
allowed_models: config.allowedModels,
|
|
203
|
+
key_ids: config.keyIds
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
function mapLiteLLMBudget(budget) {
|
|
208
|
+
return removeUndefinedValues({
|
|
209
|
+
max_budget: budget?.maxLimit,
|
|
210
|
+
budget_duration: budget?.resetDuration
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function mapLiteLLMRateLimit(rateLimit) {
|
|
214
|
+
return removeUndefinedValues({
|
|
215
|
+
tpm_limit: rateLimit?.tpmLimit ?? rateLimit?.tokenMaxLimit,
|
|
216
|
+
rpm_limit: rateLimit?.rpmLimit ?? rateLimit?.requestMaxLimit
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
class BifrostAdmin {
|
|
220
|
+
transport;
|
|
221
|
+
constructor(options) {
|
|
222
|
+
this.transport = new GatewayAdminTransport(options);
|
|
223
|
+
}
|
|
224
|
+
async createProject(options) {
|
|
225
|
+
const body = removeUndefinedValues({
|
|
226
|
+
name: options.name,
|
|
227
|
+
customer_id: options.tenantId,
|
|
228
|
+
budget: mapBifrostBudget(options.budget),
|
|
229
|
+
...options.raw
|
|
230
|
+
});
|
|
231
|
+
const response = await this.transport.request(
|
|
232
|
+
"POST",
|
|
233
|
+
"/api/governance/teams",
|
|
234
|
+
body
|
|
235
|
+
);
|
|
236
|
+
const team = toJsonRecord(response.team ?? response);
|
|
237
|
+
const id = stringValue(team.id) || stringValue(team.team_id);
|
|
238
|
+
if (!id) {
|
|
239
|
+
throw new AIError(
|
|
240
|
+
"Bifrost did not return a project id",
|
|
241
|
+
"ADMIN_INVALID_RESPONSE",
|
|
242
|
+
"bifrost"
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
id,
|
|
247
|
+
name: stringValue(team.name) || stringValue(team.team_alias) || options.name,
|
|
248
|
+
tenantId: stringValue(team.customer_id) || options.tenantId,
|
|
249
|
+
budgetId: stringValue(team.budget_id),
|
|
250
|
+
provider: "bifrost",
|
|
251
|
+
raw: response
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
async createVirtualKey(options) {
|
|
255
|
+
const body = removeUndefinedValues({
|
|
256
|
+
name: options.name,
|
|
257
|
+
description: options.description,
|
|
258
|
+
provider_configs: mapBifrostProviderConfigs(options.providerConfigs),
|
|
259
|
+
team_id: options.projectId,
|
|
260
|
+
customer_id: options.projectId ? void 0 : options.tenantId,
|
|
261
|
+
budget: mapBifrostBudget(options.budget),
|
|
262
|
+
rate_limit: mapBifrostRateLimit(options.rateLimit),
|
|
263
|
+
key_ids: options.keyIds,
|
|
264
|
+
is_active: options.isActive ?? true,
|
|
265
|
+
...options.raw
|
|
266
|
+
});
|
|
267
|
+
const response = await this.transport.request(
|
|
268
|
+
"POST",
|
|
269
|
+
"/api/governance/virtual-keys",
|
|
270
|
+
body
|
|
271
|
+
);
|
|
272
|
+
const virtualKey = toJsonRecord(
|
|
273
|
+
response.virtual_key ?? response.virtualKey ?? response
|
|
274
|
+
);
|
|
275
|
+
return {
|
|
276
|
+
id: stringValue(virtualKey.id) || stringValue(virtualKey.key_id),
|
|
277
|
+
name: stringValue(virtualKey.name) || options.name,
|
|
278
|
+
key: stringValue(virtualKey.value) || stringValue(virtualKey.key),
|
|
279
|
+
maskedKey: stringValue(virtualKey.key_name) || stringValue(virtualKey.masked_key),
|
|
280
|
+
projectId: stringValue(virtualKey.team_id) || options.projectId,
|
|
281
|
+
tenantId: stringValue(virtualKey.customer_id) || options.tenantId,
|
|
282
|
+
expiresAt: stringValue(virtualKey.expires) || stringValue(virtualKey.expires_at),
|
|
283
|
+
provider: "bifrost",
|
|
284
|
+
raw: response
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
class LiteLLMAdmin {
|
|
289
|
+
transport;
|
|
290
|
+
constructor(options) {
|
|
291
|
+
this.transport = new GatewayAdminTransport(options);
|
|
292
|
+
}
|
|
293
|
+
async createProject(options) {
|
|
294
|
+
const projectId = options.id || slugifyProjectId(options.name, options.tenantId);
|
|
295
|
+
const body = removeUndefinedValues({
|
|
296
|
+
team_id: projectId,
|
|
297
|
+
team_alias: options.name,
|
|
298
|
+
models: options.models,
|
|
299
|
+
...mapLiteLLMBudget(options.budget),
|
|
300
|
+
...mapLiteLLMRateLimit(options.rateLimit),
|
|
301
|
+
metadata: createMetadata(options),
|
|
302
|
+
blocked: options.isBlocked,
|
|
303
|
+
...options.raw
|
|
304
|
+
});
|
|
305
|
+
const response = await this.transport.request(
|
|
306
|
+
"POST",
|
|
307
|
+
"/team/new",
|
|
308
|
+
body
|
|
309
|
+
);
|
|
310
|
+
const team = toJsonRecord(response.team ?? response);
|
|
311
|
+
return {
|
|
312
|
+
id: stringValue(team.team_id) || projectId,
|
|
313
|
+
name: stringValue(team.team_alias) || stringValue(team.name) || options.name,
|
|
314
|
+
tenantId: options.tenantId,
|
|
315
|
+
provider: "litellm",
|
|
316
|
+
raw: response
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
async createVirtualKey(options) {
|
|
320
|
+
const body = removeUndefinedValues({
|
|
321
|
+
key_alias: options.name,
|
|
322
|
+
team_id: options.projectId,
|
|
323
|
+
user_id: options.userId,
|
|
324
|
+
models: options.models,
|
|
325
|
+
duration: options.duration,
|
|
326
|
+
...mapLiteLLMBudget(options.budget),
|
|
327
|
+
...mapLiteLLMRateLimit(options.rateLimit),
|
|
328
|
+
metadata: createMetadata(options),
|
|
329
|
+
aliases: options.aliases,
|
|
330
|
+
config: options.config,
|
|
331
|
+
permissions: options.permissions,
|
|
332
|
+
blocked: options.isActive === void 0 ? void 0 : !options.isActive,
|
|
333
|
+
...options.raw
|
|
334
|
+
});
|
|
335
|
+
const response = await this.transport.request(
|
|
336
|
+
"POST",
|
|
337
|
+
"/key/generate",
|
|
338
|
+
body
|
|
339
|
+
);
|
|
340
|
+
return {
|
|
341
|
+
id: stringValue(response.token_id) || stringValue(response.key_id),
|
|
342
|
+
name: stringValue(response.key_alias) || stringValue(response.key_name) || options.name,
|
|
343
|
+
key: stringValue(response.key),
|
|
344
|
+
maskedKey: stringValue(response.key_name),
|
|
345
|
+
projectId: stringValue(response.team_id) || options.projectId,
|
|
346
|
+
tenantId: options.tenantId,
|
|
347
|
+
expiresAt: stringValue(response.expires),
|
|
348
|
+
provider: "litellm",
|
|
349
|
+
raw: response
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
export {
|
|
354
|
+
BifrostAdmin as B,
|
|
355
|
+
LiteLLMAdmin as L,
|
|
356
|
+
normalizeGatewayBaseUrl as n,
|
|
357
|
+
resolveGatewayAdminBaseUrl as r
|
|
358
|
+
};
|
|
359
|
+
//# sourceMappingURL=gateway-admin-C4GFPbZF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-admin-C4GFPbZF.js","sources":["../../src/shared/providers/gateway-admin.ts"],"sourcesContent":["import type {\n AIAdminBudget,\n AIAdminInterface,\n AIAdminProject,\n AIAdminProviderConfig,\n AIAdminRateLimit,\n AIVirtualKey,\n CreateAIProjectOptions,\n CreateAIVirtualKeyOptions,\n} from '../types';\nimport { AIError } from '../types';\n\ninterface GatewayAdminTransportOptions {\n provider: string;\n baseUrl: string;\n apiKey?: string;\n username?: string;\n password?: string;\n headers?: Record<string, string>;\n timeout?: number;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nfunction stripTrailingSlash(value: string): string {\n return value.endsWith('/') ? value.slice(0, -1) : value;\n}\n\nexport function normalizeGatewayBaseUrl(baseUrl: string): string {\n return stripTrailingSlash(baseUrl.trim());\n}\n\n/**\n * Derive the gateway root URL for admin APIs from an OpenAI-compatible base URL.\n *\n * Strips known inference path suffixes iteratively so that a baseUrl such as\n * `http://host/openai/v1` collapses to the gateway root rather than to the\n * partial `http://host/openai`.\n */\nexport function deriveGatewayAdminBaseUrl(baseUrl: string): string {\n let normalized = normalizeGatewayBaseUrl(baseUrl);\n const suffixes = ['/pydanticai/v1', '/openai', '/v1'];\n let stripped = true;\n\n while (stripped) {\n stripped = false;\n for (const suffix of suffixes) {\n if (normalized.endsWith(suffix)) {\n normalized = normalized.slice(0, -suffix.length);\n stripped = true;\n break;\n }\n }\n }\n\n return normalized || normalizeGatewayBaseUrl(baseUrl);\n}\n\nexport function resolveGatewayAdminBaseUrl(\n baseUrl: string | undefined,\n adminBaseUrl: string | undefined,\n provider: string,\n): string {\n const configuredBaseUrl = adminBaseUrl || baseUrl;\n if (!configuredBaseUrl?.trim()) {\n throw new AIError(\n `${provider} baseUrl is required for admin operations`,\n 'ADMIN_BASE_URL_REQUIRED',\n provider,\n );\n }\n\n return adminBaseUrl\n ? normalizeGatewayBaseUrl(adminBaseUrl)\n : deriveGatewayAdminBaseUrl(configuredBaseUrl);\n}\n\nexport function slugifyProjectId(name: string, tenantId?: string): string {\n const value = [tenantId, name].filter(Boolean).join('-');\n const slug = value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n\n return slug || 'ai-project';\n}\n\nfunction toJsonRecord(value: unknown): JsonRecord {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as JsonRecord)\n : {};\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction encodeBasicCredentials(username: string, password: string): string {\n const value = `${username}:${password}`;\n\n if (typeof btoa === 'function') {\n return btoa(value);\n }\n\n return Buffer.from(value, 'utf8').toString('base64');\n}\n\nfunction removeUndefinedValues<T extends JsonRecord>(value: T): T {\n for (const key of Object.keys(value)) {\n if (value[key] === undefined) {\n delete value[key];\n }\n }\n\n return value;\n}\n\nfunction createMetadata(\n options: {\n tenantId?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n },\n tenantField = 'tenant_id',\n): Record<string, unknown> | undefined {\n const metadata = {\n ...options.metadata,\n };\n\n if (options.tenantId) {\n metadata[tenantField] = options.tenantId;\n }\n\n if (options.description) {\n metadata.description = options.description;\n }\n\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n}\n\nfunction responseMessage(body: unknown, fallback: string): string {\n const record = toJsonRecord(body);\n const error = toJsonRecord(record.error);\n\n return (\n stringValue(error.message) ||\n stringValue(record.message) ||\n stringValue(record.detail) ||\n fallback\n );\n}\n\nclass GatewayAdminTransport {\n private readonly baseUrl: string;\n private readonly provider: string;\n private readonly apiKey?: string;\n private readonly username?: string;\n private readonly password?: string;\n private readonly headers?: Record<string, string>;\n private readonly timeout?: number;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.provider = options.provider;\n this.baseUrl = normalizeGatewayBaseUrl(options.baseUrl);\n this.apiKey = options.apiKey;\n this.username = options.username;\n this.password = options.password;\n this.headers = options.headers;\n this.timeout = options.timeout;\n }\n\n async request<T>(\n method: string,\n path: string,\n body?: unknown,\n query?: Record<string, string | undefined>,\n ): Promise<T> {\n const url = new URL(\n `${this.baseUrl}${path.startsWith('/') ? path : `/${path}`}`,\n );\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) {\n url.searchParams.set(key, value);\n }\n }\n }\n\n const controller =\n typeof AbortController === 'undefined'\n ? undefined\n : new AbortController();\n const timeoutHandle =\n controller && this.timeout\n ? setTimeout(() => controller.abort(), this.timeout)\n : undefined;\n\n try {\n const response = await fetch(url, {\n method,\n headers: {\n Accept: 'application/json',\n ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n ...this.headers,\n ...this.createAuthHeaders(),\n },\n body: body === undefined ? undefined : JSON.stringify(body),\n signal: controller?.signal,\n });\n\n const text = await response.text();\n const parsed = text ? this.parseJson(text) : undefined;\n\n if (!response.ok) {\n throw this.mapResponseError(response, parsed);\n }\n\n return parsed as T;\n } catch (error) {\n if (error instanceof AIError) {\n throw error;\n }\n\n throw new AIError(\n `${this.provider} admin request failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n 'ADMIN_REQUEST_FAILED',\n this.provider,\n );\n } finally {\n if (timeoutHandle) {\n clearTimeout(timeoutHandle);\n }\n }\n }\n\n private createAuthHeaders(): Record<string, string> {\n if (this.username && this.password) {\n return {\n Authorization: `Basic ${encodeBasicCredentials(\n this.username,\n this.password,\n )}`,\n };\n }\n\n return this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {};\n }\n\n private parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch (_error) {\n return { message: text };\n }\n }\n\n private mapResponseError(response: Response, body: unknown): AIError {\n const message = responseMessage(\n body,\n `${this.provider} admin request failed with ${response.status}`,\n );\n\n if (response.status === 401 || response.status === 403) {\n return new AIError(message, 'AUTH_ERROR', this.provider);\n }\n\n if (response.status === 429) {\n return new AIError(message, 'RATE_LIMIT', this.provider, undefined, true);\n }\n\n return new AIError(\n message,\n `ADMIN_HTTP_${response.status}`,\n this.provider,\n undefined,\n response.status >= 500,\n );\n }\n}\n\nfunction mapBifrostBudget(budget?: AIAdminBudget): JsonRecord | undefined {\n if (!budget) return undefined;\n\n return removeUndefinedValues({\n max_limit: budget.maxLimit,\n reset_duration: budget.resetDuration,\n calendar_aligned: budget.calendarAligned,\n });\n}\n\nfunction mapBifrostRateLimit(\n rateLimit?: AIAdminRateLimit,\n): JsonRecord | undefined {\n if (!rateLimit) return undefined;\n\n return removeUndefinedValues({\n token_max_limit: rateLimit.tokenMaxLimit ?? rateLimit.tpmLimit,\n token_reset_duration: rateLimit.tokenResetDuration,\n request_max_limit: rateLimit.requestMaxLimit ?? rateLimit.rpmLimit,\n request_reset_duration: rateLimit.requestResetDuration,\n });\n}\n\nfunction mapBifrostProviderConfigs(\n configs?: AIAdminProviderConfig[],\n): JsonRecord[] | undefined {\n if (!configs) return undefined;\n\n return configs.map((config) =>\n removeUndefinedValues({\n provider: config.provider,\n weight: config.weight,\n allowed_models: config.allowedModels,\n key_ids: config.keyIds,\n }),\n );\n}\n\nfunction mapLiteLLMBudget(\n budget?: AIAdminBudget,\n): Pick<JsonRecord, 'max_budget' | 'budget_duration'> {\n return removeUndefinedValues({\n max_budget: budget?.maxLimit,\n budget_duration: budget?.resetDuration,\n });\n}\n\nfunction mapLiteLLMRateLimit(\n rateLimit?: AIAdminRateLimit,\n): Pick<JsonRecord, 'tpm_limit' | 'rpm_limit'> {\n return removeUndefinedValues({\n tpm_limit: rateLimit?.tpmLimit ?? rateLimit?.tokenMaxLimit,\n rpm_limit: rateLimit?.rpmLimit ?? rateLimit?.requestMaxLimit,\n });\n}\n\nexport class BifrostAdmin implements AIAdminInterface {\n private readonly transport: GatewayAdminTransport;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.transport = new GatewayAdminTransport(options);\n }\n\n async createProject(\n options: CreateAIProjectOptions,\n ): Promise<AIAdminProject> {\n const body = removeUndefinedValues({\n name: options.name,\n customer_id: options.tenantId,\n budget: mapBifrostBudget(options.budget),\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/api/governance/teams',\n body,\n );\n const team = toJsonRecord(response.team ?? response);\n const id = stringValue(team.id) || stringValue(team.team_id);\n\n if (!id) {\n throw new AIError(\n 'Bifrost did not return a project id',\n 'ADMIN_INVALID_RESPONSE',\n 'bifrost',\n );\n }\n\n return {\n id,\n name:\n stringValue(team.name) || stringValue(team.team_alias) || options.name,\n tenantId: stringValue(team.customer_id) || options.tenantId,\n budgetId: stringValue(team.budget_id),\n provider: 'bifrost',\n raw: response,\n };\n }\n\n async createVirtualKey(\n options: CreateAIVirtualKeyOptions,\n ): Promise<AIVirtualKey> {\n const body = removeUndefinedValues({\n name: options.name,\n description: options.description,\n provider_configs: mapBifrostProviderConfigs(options.providerConfigs),\n team_id: options.projectId,\n customer_id: options.projectId ? undefined : options.tenantId,\n budget: mapBifrostBudget(options.budget),\n rate_limit: mapBifrostRateLimit(options.rateLimit),\n key_ids: options.keyIds,\n is_active: options.isActive ?? true,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/api/governance/virtual-keys',\n body,\n );\n const virtualKey = toJsonRecord(\n response.virtual_key ?? response.virtualKey ?? response,\n );\n\n return {\n id: stringValue(virtualKey.id) || stringValue(virtualKey.key_id),\n name: stringValue(virtualKey.name) || options.name,\n key: stringValue(virtualKey.value) || stringValue(virtualKey.key),\n maskedKey:\n stringValue(virtualKey.key_name) || stringValue(virtualKey.masked_key),\n projectId: stringValue(virtualKey.team_id) || options.projectId,\n tenantId: stringValue(virtualKey.customer_id) || options.tenantId,\n expiresAt:\n stringValue(virtualKey.expires) || stringValue(virtualKey.expires_at),\n provider: 'bifrost',\n raw: response,\n };\n }\n}\n\nexport class LiteLLMAdmin implements AIAdminInterface {\n private readonly transport: GatewayAdminTransport;\n\n constructor(options: GatewayAdminTransportOptions) {\n this.transport = new GatewayAdminTransport(options);\n }\n\n async createProject(\n options: CreateAIProjectOptions,\n ): Promise<AIAdminProject> {\n const projectId =\n options.id || slugifyProjectId(options.name, options.tenantId);\n const body = removeUndefinedValues({\n team_id: projectId,\n team_alias: options.name,\n models: options.models,\n ...mapLiteLLMBudget(options.budget),\n ...mapLiteLLMRateLimit(options.rateLimit),\n metadata: createMetadata(options),\n blocked: options.isBlocked,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/team/new',\n body,\n );\n const team = toJsonRecord(response.team ?? response);\n\n return {\n id: stringValue(team.team_id) || projectId,\n name:\n stringValue(team.team_alias) || stringValue(team.name) || options.name,\n tenantId: options.tenantId,\n provider: 'litellm',\n raw: response,\n };\n }\n\n async createVirtualKey(\n options: CreateAIVirtualKeyOptions,\n ): Promise<AIVirtualKey> {\n const body = removeUndefinedValues({\n key_alias: options.name,\n team_id: options.projectId,\n user_id: options.userId,\n models: options.models,\n duration: options.duration,\n ...mapLiteLLMBudget(options.budget),\n ...mapLiteLLMRateLimit(options.rateLimit),\n metadata: createMetadata(options),\n aliases: options.aliases,\n config: options.config,\n permissions: options.permissions,\n blocked: options.isActive === undefined ? undefined : !options.isActive,\n ...options.raw,\n });\n\n const response = await this.transport.request<JsonRecord>(\n 'POST',\n '/key/generate',\n body,\n );\n\n return {\n id: stringValue(response.token_id) || stringValue(response.key_id),\n name:\n stringValue(response.key_alias) ||\n stringValue(response.key_name) ||\n options.name,\n key: stringValue(response.key),\n maskedKey: stringValue(response.key_name),\n projectId: stringValue(response.team_id) || options.projectId,\n tenantId: options.tenantId,\n expiresAt: stringValue(response.expires),\n provider: 'litellm',\n raw: response,\n };\n }\n}\n"],"names":[],"mappings":"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"}
|