@juspay/neurolink 12.22.1 → 12.23.1
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/CHANGELOG.md +2 -2
- package/dist/adapters/providerImageAdapter.js +16 -11
- package/dist/browser/neurolink.min.js +386 -386
- package/dist/cli/factories/commandFactory.js +26 -3
- package/dist/constants/enums.d.ts +10 -0
- package/dist/constants/enums.js +11 -0
- package/dist/factories/providerDescriptors.d.ts +1 -1
- package/dist/factories/providerDescriptors.js +15 -13
- package/dist/image-gen/ImageGenService.js +16 -14
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/mcp/externalServerManager.d.ts +9 -0
- package/dist/mcp/externalServerManager.js +88 -16
- package/dist/neurolink.js +18 -11
- package/dist/providers/amazonBedrock/client.js +30 -1
- package/dist/providers/catalog/friendli.json +130 -0
- package/dist/providers/catalog/index.generated.d.ts +1 -1
- package/dist/providers/catalog/index.generated.js +3 -0
- package/dist/providers/catalog/mistral.json +1 -2
- package/dist/providers/catalog/schema.js +34 -0
- package/dist/providers/googleAiStudio/client.js +18 -2
- package/dist/providers/googleVertex/client.js +13 -4
- package/dist/providers/recraft.js +8 -1
- package/dist/proxy/accountRanking.d.ts +22 -0
- package/dist/proxy/accountRanking.js +86 -0
- package/dist/proxy/proxyConfig.js +78 -17
- package/dist/server/routes/claudeProxyRoutes.d.ts +12 -4
- package/dist/server/routes/claudeProxyRoutes.js +54 -84
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/externalMcp.d.ts +20 -2
- package/dist/types/generate.d.ts +6 -1
- package/dist/types/mcp.d.ts +17 -0
- package/dist/types/providerCatalog.generated.d.ts +2 -2
- package/dist/types/providers.d.ts +4 -0
- package/dist/types/proxy.d.ts +3 -0
- package/dist/utils/imageDetection.d.ts +10 -0
- package/dist/utils/imageDetection.js +38 -12
- package/docs-site/static/search-index.json +1 -1
- package/package.json +3 -2
|
@@ -213,6 +213,36 @@ const CODEX_REASONING_EFFORTS = [
|
|
|
213
213
|
function isCodexReasoningEffort(value) {
|
|
214
214
|
return CODEX_REASONING_EFFORTS.some((effort) => effort === value);
|
|
215
215
|
}
|
|
216
|
+
function kebabToCamelRoutingKey(kebabKey) {
|
|
217
|
+
return kebabKey.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Read one of the eight routing keys that predate #1787's five newer keys,
|
|
221
|
+
* accepting either spelling and treating a `null` value under either
|
|
222
|
+
* spelling as "unset" so it falls back to the caller's default instead of
|
|
223
|
+
* failing validation.
|
|
224
|
+
*
|
|
225
|
+
* `??` already treats a `null` kebab value the same as an absent one and
|
|
226
|
+
* falls through to the camel spelling — that precedence must not change (a
|
|
227
|
+
* `null` kebab key must not mask a non-null camel value) — so the only gap
|
|
228
|
+
* is a combined value that still resolves to `null` (camel-only `null`, or
|
|
229
|
+
* both spellings `null`): that case is mapped to `undefined` here so every
|
|
230
|
+
* existing `!== undefined` guard and default keeps working unchanged.
|
|
231
|
+
*
|
|
232
|
+
* `wasNull` is true exactly when the resolved value became `undefined`
|
|
233
|
+
* *because* one of the spellings was explicitly `null` — never merely
|
|
234
|
+
* because both were absent — so callers can warn once per null key without
|
|
235
|
+
* warning on ordinary omission.
|
|
236
|
+
*/
|
|
237
|
+
function readLegacyRoutingKey(routing, kebabKey) {
|
|
238
|
+
const camelKey = kebabToCamelRoutingKey(kebabKey);
|
|
239
|
+
const rawKebab = routing[kebabKey];
|
|
240
|
+
const rawCamel = routing[camelKey];
|
|
241
|
+
const combined = rawKebab ?? rawCamel;
|
|
242
|
+
const value = combined === null ? undefined : combined;
|
|
243
|
+
const wasNull = value === undefined && (rawKebab === null || rawCamel === null);
|
|
244
|
+
return { value, wasNull };
|
|
245
|
+
}
|
|
216
246
|
/**
|
|
217
247
|
* Validate the shape of a parsed proxy config.
|
|
218
248
|
* Returns an array of human-readable error strings (empty = valid).
|
|
@@ -239,7 +269,7 @@ export function validateProxyConfig(config) {
|
|
|
239
269
|
}
|
|
240
270
|
if (hasRouting) {
|
|
241
271
|
const routing = cfg.routing;
|
|
242
|
-
const rawFallback = routing
|
|
272
|
+
const rawFallback = readLegacyRoutingKey(routing, "fallback-chain").value;
|
|
243
273
|
if (Array.isArray(rawFallback)) {
|
|
244
274
|
rawFallback.forEach((entry, index) => {
|
|
245
275
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
@@ -261,7 +291,7 @@ export function validateProxyConfig(config) {
|
|
|
261
291
|
}
|
|
262
292
|
});
|
|
263
293
|
}
|
|
264
|
-
const rawAccountAllowlist = routing
|
|
294
|
+
const rawAccountAllowlist = readLegacyRoutingKey(routing, "account-allowlist").value;
|
|
265
295
|
if (rawAccountAllowlist !== undefined) {
|
|
266
296
|
if (!Array.isArray(rawAccountAllowlist)) {
|
|
267
297
|
errors.push("routing.account-allowlist must be an array of non-empty strings");
|
|
@@ -274,7 +304,7 @@ export function validateProxyConfig(config) {
|
|
|
274
304
|
});
|
|
275
305
|
}
|
|
276
306
|
}
|
|
277
|
-
const rawQuotaRouting = routing
|
|
307
|
+
const rawQuotaRouting = readLegacyRoutingKey(routing, "quota-routing").value;
|
|
278
308
|
const normalizedQuotaRouting = typeof rawQuotaRouting === "string"
|
|
279
309
|
? rawQuotaRouting.trim().toLowerCase()
|
|
280
310
|
: undefined;
|
|
@@ -287,14 +317,14 @@ export function validateProxyConfig(config) {
|
|
|
287
317
|
// Without this a typo (`use-overage: nevr`) loads cleanly and silently
|
|
288
318
|
// falls back to "auto" — the operator asked to block paid extra usage and
|
|
289
319
|
// gets provider-driven overage instead.
|
|
290
|
-
const rawUseOverage = routing
|
|
320
|
+
const rawUseOverage = readLegacyRoutingKey(routing, "use-overage").value;
|
|
291
321
|
if (rawUseOverage !== undefined &&
|
|
292
322
|
!["auto", "always", "never"].includes(typeof rawUseOverage === "string"
|
|
293
323
|
? rawUseOverage.trim().toLowerCase()
|
|
294
324
|
: "")) {
|
|
295
325
|
errors.push("routing.use-overage must be auto, always, or never");
|
|
296
326
|
}
|
|
297
|
-
const rawAutoFallback = routing
|
|
327
|
+
const rawAutoFallback = readLegacyRoutingKey(routing, "auto-fallback").value;
|
|
298
328
|
const normalizedAutoFallback = typeof rawAutoFallback === "string"
|
|
299
329
|
? rawAutoFallback.trim().toLowerCase()
|
|
300
330
|
: undefined;
|
|
@@ -304,7 +334,7 @@ export function validateProxyConfig(config) {
|
|
|
304
334
|
normalizedAutoFallback !== "false") {
|
|
305
335
|
errors.push("routing.auto-fallback must be a boolean");
|
|
306
336
|
}
|
|
307
|
-
const rawMaxInflight = routing
|
|
337
|
+
const rawMaxInflight = readLegacyRoutingKey(routing, "max-inflight-per-account").value;
|
|
308
338
|
if (rawMaxInflight !== undefined &&
|
|
309
339
|
(typeof rawMaxInflight !== "number" ||
|
|
310
340
|
!Number.isInteger(rawMaxInflight) ||
|
|
@@ -312,7 +342,7 @@ export function validateProxyConfig(config) {
|
|
|
312
342
|
rawMaxInflight > MAX_MAX_INFLIGHT_PER_ACCOUNT)) {
|
|
313
343
|
errors.push("routing.max-inflight-per-account must be an integer between 1 and 20");
|
|
314
344
|
}
|
|
315
|
-
const rawSessionSoftLimit = routing
|
|
345
|
+
const rawSessionSoftLimit = readLegacyRoutingKey(routing, "session-soft-limit").value;
|
|
316
346
|
if (rawSessionSoftLimit !== undefined) {
|
|
317
347
|
const sessionSoftLimit = Number(rawSessionSoftLimit);
|
|
318
348
|
if (!Number.isFinite(sessionSoftLimit) ||
|
|
@@ -321,7 +351,7 @@ export function validateProxyConfig(config) {
|
|
|
321
351
|
errors.push("routing.session-soft-limit must be a number in (0, 1]");
|
|
322
352
|
}
|
|
323
353
|
}
|
|
324
|
-
const rawSessionResetToleranceMs = routing
|
|
354
|
+
const rawSessionResetToleranceMs = readLegacyRoutingKey(routing, "session-reset-tolerance-ms").value;
|
|
325
355
|
if (rawSessionResetToleranceMs !== undefined) {
|
|
326
356
|
const sessionResetToleranceMs = Number(rawSessionResetToleranceMs);
|
|
327
357
|
if (!Number.isInteger(sessionResetToleranceMs) ||
|
|
@@ -439,7 +469,11 @@ function parseRoutingConfig(raw) {
|
|
|
439
469
|
.filter((m) => m !== null);
|
|
440
470
|
}
|
|
441
471
|
// Fallback chain (accept kebab-case or camelCase)
|
|
442
|
-
const
|
|
472
|
+
const fallbackChainRead = readLegacyRoutingKey(raw, "fallback-chain");
|
|
473
|
+
if (fallbackChainRead.wasNull) {
|
|
474
|
+
logger.warn("[proxy-config] routing.fallback-chain is null; using the default");
|
|
475
|
+
}
|
|
476
|
+
const rawFallback = fallbackChainRead.value;
|
|
443
477
|
if (Array.isArray(rawFallback)) {
|
|
444
478
|
result.fallbackChain = rawFallback
|
|
445
479
|
.filter((e) => e !== null && typeof e === "object")
|
|
@@ -469,7 +503,11 @@ function parseRoutingConfig(raw) {
|
|
|
469
503
|
if (Array.isArray(rawPassthrough)) {
|
|
470
504
|
result.passthroughModels = rawPassthrough.map(String);
|
|
471
505
|
}
|
|
472
|
-
const
|
|
506
|
+
const quotaRoutingRead = readLegacyRoutingKey(raw, "quota-routing");
|
|
507
|
+
if (quotaRoutingRead.wasNull) {
|
|
508
|
+
logger.warn("[proxy-config] routing.quota-routing is null; using the default");
|
|
509
|
+
}
|
|
510
|
+
const rawQuotaRouting = quotaRoutingRead.value;
|
|
473
511
|
if (rawQuotaRouting !== undefined) {
|
|
474
512
|
if (typeof rawQuotaRouting === "boolean") {
|
|
475
513
|
result.quotaRouting = rawQuotaRouting;
|
|
@@ -482,7 +520,11 @@ function parseRoutingConfig(raw) {
|
|
|
482
520
|
logger.warn(`[proxy-config] Ignoring routing.quotaRouting: expected boolean, got ${typeof rawQuotaRouting}`);
|
|
483
521
|
}
|
|
484
522
|
}
|
|
485
|
-
const
|
|
523
|
+
const useOverageRead = readLegacyRoutingKey(raw, "use-overage");
|
|
524
|
+
if (useOverageRead.wasNull) {
|
|
525
|
+
logger.warn("[proxy-config] routing.use-overage is null; using the default");
|
|
526
|
+
}
|
|
527
|
+
const rawUseOverage = useOverageRead.value;
|
|
486
528
|
if (rawUseOverage !== undefined) {
|
|
487
529
|
const normalized = typeof rawUseOverage === "string"
|
|
488
530
|
? rawUseOverage.trim().toLowerCase()
|
|
@@ -496,7 +538,11 @@ function parseRoutingConfig(raw) {
|
|
|
496
538
|
logger.warn(`[proxy-config] Ignoring routing.useOverage: expected auto|always|never, got ${String(rawUseOverage)}`);
|
|
497
539
|
}
|
|
498
540
|
}
|
|
499
|
-
const
|
|
541
|
+
const autoFallbackRead = readLegacyRoutingKey(raw, "auto-fallback");
|
|
542
|
+
if (autoFallbackRead.wasNull) {
|
|
543
|
+
logger.warn("[proxy-config] routing.auto-fallback is null; using the default");
|
|
544
|
+
}
|
|
545
|
+
const rawAutoFallback = autoFallbackRead.value;
|
|
500
546
|
if (rawAutoFallback !== undefined) {
|
|
501
547
|
if (typeof rawAutoFallback === "boolean") {
|
|
502
548
|
result.autoFallback = rawAutoFallback;
|
|
@@ -509,7 +555,11 @@ function parseRoutingConfig(raw) {
|
|
|
509
555
|
logger.warn(`[proxy-config] Ignoring routing.autoFallback: expected boolean, got ${typeof rawAutoFallback}`);
|
|
510
556
|
}
|
|
511
557
|
}
|
|
512
|
-
const
|
|
558
|
+
const maxInflightRead = readLegacyRoutingKey(raw, "max-inflight-per-account");
|
|
559
|
+
if (maxInflightRead.wasNull) {
|
|
560
|
+
logger.warn("[proxy-config] routing.max-inflight-per-account is null; using the default");
|
|
561
|
+
}
|
|
562
|
+
const rawMaxInflight = maxInflightRead.value;
|
|
513
563
|
if (rawMaxInflight !== undefined) {
|
|
514
564
|
if (typeof rawMaxInflight === "number" &&
|
|
515
565
|
Number.isInteger(rawMaxInflight) &&
|
|
@@ -521,7 +571,11 @@ function parseRoutingConfig(raw) {
|
|
|
521
571
|
logger.warn(`[proxy-config] Ignoring routing.maxInflightPerAccount: expected integer between 1 and 20, got ${String(rawMaxInflight)}`);
|
|
522
572
|
}
|
|
523
573
|
}
|
|
524
|
-
const
|
|
574
|
+
const sessionSoftLimitRead = readLegacyRoutingKey(raw, "session-soft-limit");
|
|
575
|
+
if (sessionSoftLimitRead.wasNull) {
|
|
576
|
+
logger.warn("[proxy-config] routing.session-soft-limit is null; using the default");
|
|
577
|
+
}
|
|
578
|
+
const rawSessionSoftLimit = sessionSoftLimitRead.value;
|
|
525
579
|
if (rawSessionSoftLimit !== undefined) {
|
|
526
580
|
const sessionSoftLimit = Number(rawSessionSoftLimit);
|
|
527
581
|
if (Number.isFinite(sessionSoftLimit) &&
|
|
@@ -533,7 +587,11 @@ function parseRoutingConfig(raw) {
|
|
|
533
587
|
logger.warn(`[proxy-config] Ignoring routing.sessionSoftLimit: expected number in (0, 1], got ${String(rawSessionSoftLimit)}`);
|
|
534
588
|
}
|
|
535
589
|
}
|
|
536
|
-
const
|
|
590
|
+
const sessionResetToleranceMsRead = readLegacyRoutingKey(raw, "session-reset-tolerance-ms");
|
|
591
|
+
if (sessionResetToleranceMsRead.wasNull) {
|
|
592
|
+
logger.warn("[proxy-config] routing.session-reset-tolerance-ms is null; using the default");
|
|
593
|
+
}
|
|
594
|
+
const rawSessionResetToleranceMs = sessionResetToleranceMsRead.value;
|
|
537
595
|
if (rawSessionResetToleranceMs !== undefined) {
|
|
538
596
|
const sessionResetToleranceMs = Number(rawSessionResetToleranceMs);
|
|
539
597
|
if (Number.isInteger(sessionResetToleranceMs) &&
|
|
@@ -558,8 +616,11 @@ function parseRoutingConfig(raw) {
|
|
|
558
616
|
`string, got ${typeof rawPrimary}`);
|
|
559
617
|
}
|
|
560
618
|
}
|
|
561
|
-
const
|
|
562
|
-
|
|
619
|
+
const accountAllowlistRead = readLegacyRoutingKey(raw, "account-allowlist");
|
|
620
|
+
if (accountAllowlistRead.wasNull) {
|
|
621
|
+
logger.warn("[proxy-config] routing.account-allowlist is null; using the default");
|
|
622
|
+
}
|
|
623
|
+
const rawAccountAllowlist = accountAllowlistRead.value;
|
|
563
624
|
if (Array.isArray(rawAccountAllowlist)) {
|
|
564
625
|
result.accountAllowlist = [
|
|
565
626
|
...new Set(rawAccountAllowlist.map((entry) => String(entry).trim())),
|
|
@@ -3,10 +3,12 @@ import { ProxyTracer } from "../../proxy/proxyTracer.js";
|
|
|
3
3
|
import { isPermanentRefreshFailure } from "../../proxy/tokenRefresh.js";
|
|
4
4
|
import type { ProxyAccountDirectoryOverride } from "../../types/index.js";
|
|
5
5
|
import type { AccountAllowlist, AccountAdmissionLease, JsonObject, AccountCooldownPlan, AccountQuota, AccountQuotaWindow, AccountUsageFetchResult, AnthropicAttemptLogger, AnthropicAuthRetryResult, AnthropicEntitlementFailure, AnthropicInvalidRequestFailure, AnthropicLoopState, AnthropicScopedExhaustion, AnthropicNonOkResult, AnthropicSuccessResult, AnthropicUpstreamBody, AnthropicUpstreamBodyBuilder, AnthropicUpstreamFetchResult, ClaudeFinalRequestLogger, ClaudeLoggedErrorBuilder, ClaudeRequest, ClaudeProxyRouteRuntimeOptions, ModelRouterInterface, ParsedClaudeError, ProxyAccountRoutingDecision, ProxyAccountSortMetrics, ProxyBodyCaptureLogger, ProxyLimitsRefreshResponse, ProxyQuotaCooldownUpdate, ProxyOveragePolicy, ProxyPassthroughAccount, QueuedAccountAdmission, RouteGroup, RuntimeAccountState, ServerContext, StreamTerminalOutcome } from "../../types/index.js";
|
|
6
|
-
declare function tryAcquireAccountAdmission(accountKey: string, capacity: number | undefined): AccountAdmissionLease | undefined;
|
|
7
|
-
|
|
8
|
-
declare function
|
|
9
|
-
declare function
|
|
6
|
+
declare function tryAcquireAccountAdmission(accountKey: string, capacity: number | undefined, generation?: number): AccountAdmissionLease | undefined;
|
|
7
|
+
/** Current in-flight request count for one account, unlimited or capped. */
|
|
8
|
+
declare function getAccountInflight(accountKey: string): number;
|
|
9
|
+
declare function enqueueAccountAdmission(accountKey: string, capacity: number, generation?: number): QueuedAccountAdmission;
|
|
10
|
+
declare function acquireAccountAdmission(accountKey: string, capacity: number, abortSignal?: AbortSignal, timeoutMs?: number, generation?: number): Promise<AccountAdmissionLease | undefined>;
|
|
11
|
+
declare function acquireFirstAvailableAccountAdmission(accountKeys: string[], capacity: number, abortSignal?: AbortSignal, timeoutMs?: number, generation?: number): Promise<{
|
|
10
12
|
accountKey: string;
|
|
11
13
|
lease: AccountAdmissionLease;
|
|
12
14
|
} | undefined>;
|
|
@@ -119,6 +121,10 @@ declare function evaluateScopedExhaustion(accounts: ProxyPassthroughAccount[], r
|
|
|
119
121
|
eligible: ProxyPassthroughAccount[];
|
|
120
122
|
exhaustion: AnthropicScopedExhaustion | null;
|
|
121
123
|
};
|
|
124
|
+
declare function orderAccountsByQuotaWithMetrics(accounts: ProxyPassthroughAccount[], now: number, primaryKey: string | undefined, sessionSoftLimit: number, sessionResetToleranceMs: number, requestedModel?: string): {
|
|
125
|
+
orderedAccounts: ProxyPassthroughAccount[];
|
|
126
|
+
metricsByKey: Map<string, ProxyAccountSortMetrics>;
|
|
127
|
+
};
|
|
122
128
|
/**
|
|
123
129
|
* Order accounts to MAXIMIZE quota utilization (fill-first, smart order):
|
|
124
130
|
* spend the overall weekly allowance that expires SOONEST first, so quota
|
|
@@ -496,6 +502,7 @@ export declare const __testHooks: {
|
|
|
496
502
|
getStreamFailureDetails: typeof getStreamFailureDetails;
|
|
497
503
|
trackUpstreamReadableStream: typeof trackUpstreamReadableStream;
|
|
498
504
|
orderAccountsByQuota: typeof orderAccountsByQuota;
|
|
505
|
+
orderAccountsByQuotaWithMetrics: typeof orderAccountsByQuotaWithMetrics;
|
|
499
506
|
scheduleAdaptiveQuotaRefreshes: typeof scheduleAdaptiveQuotaRefreshes;
|
|
500
507
|
scheduleHandoffQuotaRefresh: typeof scheduleHandoffQuotaRefresh;
|
|
501
508
|
getQuotaRefreshState: (key: string) => import("../../index.js").ProxyQuotaRefreshRuntimeState;
|
|
@@ -526,6 +533,7 @@ export declare const __testHooks: {
|
|
|
526
533
|
acquireFirstAvailableAccountAdmission: typeof acquireFirstAvailableAccountAdmission;
|
|
527
534
|
tryAcquireAccountAdmission: typeof tryAcquireAccountAdmission;
|
|
528
535
|
enqueueAccountAdmission: typeof enqueueAccountAdmission;
|
|
536
|
+
getAccountInflight: typeof getAccountInflight;
|
|
529
537
|
getAccountAdmissionSnapshot: (accountKey: string) => {
|
|
530
538
|
active: number;
|
|
531
539
|
waiting: number;
|
|
@@ -24,6 +24,7 @@ import { fetchCodexAccountUsage, listCodexAccountsForUsage, resolveProxyStatusAc
|
|
|
24
24
|
import { AccountQuotaRefreshCoordinator } from "../../proxy/accountQuotaRefreshCoordinator.js";
|
|
25
25
|
import { ProviderTransportCoordinator } from "../../proxy/providerTransportCoordinator.js";
|
|
26
26
|
import { MAX_COOLDOWN_MS_BY_REASON } from "../../proxy/routingEvidence.js";
|
|
27
|
+
import { compareExpiryFirst, rankAccounts, } from "../../proxy/accountRanking.js";
|
|
27
28
|
import { buildProxyLimitHeaders, summarizePoolHeadroom, } from "../../proxy/quotaHeaders.js";
|
|
28
29
|
import { buildClaudeError, ClaudeStreamSerializer, parseClaudeRequest, serializeClaudeResponse, } from "../../proxy/claudeFormat.js";
|
|
29
30
|
import { getProxyUpstreamFailure } from "../../proxy/proxyFailureDetails.js";
|
|
@@ -261,9 +262,6 @@ const transientCooldownAdmissionSchedules = new Map();
|
|
|
261
262
|
* make room for another stream on the same account.
|
|
262
263
|
*/
|
|
263
264
|
const accountAdmissionStates = new Map();
|
|
264
|
-
const unlimitedAccountAdmissionLease = {
|
|
265
|
-
release: () => undefined,
|
|
266
|
-
};
|
|
267
265
|
function getAccountAdmissionState(accountKey) {
|
|
268
266
|
let state = accountAdmissionStates.get(accountKey);
|
|
269
267
|
if (!state) {
|
|
@@ -282,6 +280,32 @@ function drainAccountAdmissionWaiters(accountKey, state) {
|
|
|
282
280
|
waiter.resolve(createAccountAdmissionLease(accountKey, state));
|
|
283
281
|
}
|
|
284
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Admits, in FIFO order and ignoring the capacity each one queued with, every
|
|
285
|
+
* waiter that queued under an older runtime-config generation than the
|
|
286
|
+
* uncapped request now acquiring. Each request reads the cap from the snapshot
|
|
287
|
+
* it arrived with, so only a NEWER uncapped snapshot shows that a reload
|
|
288
|
+
* removed the waiter's cap — and uncapped arrivals count toward `active`, so
|
|
289
|
+
* that waiter would otherwise never drain. An uncapped request from an older
|
|
290
|
+
* snapshot (one that predates a reload adding the cap) or from the same one
|
|
291
|
+
* leaves waiters queued: their cap is still current. With no generation there
|
|
292
|
+
* is no runtime config store, the cap cannot change, and nothing is admitted.
|
|
293
|
+
*/
|
|
294
|
+
function admitWaitersOfRemovedCap(accountKey, state, generation) {
|
|
295
|
+
if (generation === undefined) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const queuedUnderOlderSnapshot = (waiter) => waiter.generation !== undefined && waiter.generation < generation;
|
|
299
|
+
const admitted = state.waiters.filter(queuedUnderOlderSnapshot);
|
|
300
|
+
if (admitted.length === 0) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
state.waiters = state.waiters.filter((waiter) => !queuedUnderOlderSnapshot(waiter));
|
|
304
|
+
for (const waiter of admitted) {
|
|
305
|
+
state.active += 1;
|
|
306
|
+
waiter.resolve(createAccountAdmissionLease(accountKey, state));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
285
309
|
function createAccountAdmissionLease(accountKey, state) {
|
|
286
310
|
let released = false;
|
|
287
311
|
return {
|
|
@@ -301,18 +325,24 @@ function discardAccountAdmissionState(accountKey, state) {
|
|
|
301
325
|
accountAdmissionStates.delete(accountKey);
|
|
302
326
|
}
|
|
303
327
|
}
|
|
304
|
-
function tryAcquireAccountAdmission(accountKey, capacity) {
|
|
328
|
+
function tryAcquireAccountAdmission(accountKey, capacity, generation) {
|
|
305
329
|
const normalizedCapacity = normalizeMaxInflightPerAccount(capacity);
|
|
330
|
+
const state = getAccountAdmissionState(accountKey);
|
|
306
331
|
if (normalizedCapacity === undefined) {
|
|
307
|
-
|
|
332
|
+
admitWaitersOfRemovedCap(accountKey, state, generation);
|
|
333
|
+
state.active += 1;
|
|
334
|
+
return createAccountAdmissionLease(accountKey, state);
|
|
308
335
|
}
|
|
309
|
-
const state = getAccountAdmissionState(accountKey);
|
|
310
336
|
if (state.waiters.length > 0 || state.active >= normalizedCapacity) {
|
|
311
337
|
return undefined;
|
|
312
338
|
}
|
|
313
339
|
state.active += 1;
|
|
314
340
|
return createAccountAdmissionLease(accountKey, state);
|
|
315
341
|
}
|
|
342
|
+
/** Current in-flight request count for one account, unlimited or capped. */
|
|
343
|
+
function getAccountInflight(accountKey) {
|
|
344
|
+
return accountAdmissionStates.get(accountKey)?.active ?? 0;
|
|
345
|
+
}
|
|
316
346
|
function isAccountAdmissionAvailable(accountKey, capacity) {
|
|
317
347
|
const normalizedCapacity = normalizeMaxInflightPerAccount(capacity);
|
|
318
348
|
if (normalizedCapacity === undefined) {
|
|
@@ -321,7 +351,7 @@ function isAccountAdmissionAvailable(accountKey, capacity) {
|
|
|
321
351
|
const state = accountAdmissionStates.get(accountKey);
|
|
322
352
|
return (!state || (state.waiters.length === 0 && state.active < normalizedCapacity));
|
|
323
353
|
}
|
|
324
|
-
function enqueueAccountAdmission(accountKey, capacity) {
|
|
354
|
+
function enqueueAccountAdmission(accountKey, capacity, generation) {
|
|
325
355
|
// Validate BEFORE getAccountAdmissionState(), which inserts into the map as a
|
|
326
356
|
// side effect. Throwing after it would strand an empty entry for an account
|
|
327
357
|
// that never got admitted — and the throw path never calls
|
|
@@ -339,6 +369,7 @@ function enqueueAccountAdmission(accountKey, capacity) {
|
|
|
339
369
|
});
|
|
340
370
|
const waiter = {
|
|
341
371
|
capacity: normalizedCapacity,
|
|
372
|
+
generation,
|
|
342
373
|
resolve: (lease) => {
|
|
343
374
|
queued = false;
|
|
344
375
|
grantedLease = lease;
|
|
@@ -370,8 +401,8 @@ function enqueueAccountAdmission(accountKey, capacity) {
|
|
|
370
401
|
},
|
|
371
402
|
};
|
|
372
403
|
}
|
|
373
|
-
async function acquireAccountAdmission(accountKey, capacity, abortSignal, timeoutMs = MAX_TRANSIENT_QUEUE_WAIT_MS) {
|
|
374
|
-
const queued = enqueueAccountAdmission(accountKey, capacity);
|
|
404
|
+
async function acquireAccountAdmission(accountKey, capacity, abortSignal, timeoutMs = MAX_TRANSIENT_QUEUE_WAIT_MS, generation) {
|
|
405
|
+
const queued = enqueueAccountAdmission(accountKey, capacity, generation);
|
|
375
406
|
try {
|
|
376
407
|
return await withTimeout(raceWithAbort(queued.promise, abortSignal), timeoutMs, `Account admission for ${accountKey} timed out after ${timeoutMs}ms`);
|
|
377
408
|
}
|
|
@@ -383,8 +414,8 @@ async function acquireAccountAdmission(accountKey, capacity, abortSignal, timeou
|
|
|
383
414
|
return undefined;
|
|
384
415
|
}
|
|
385
416
|
}
|
|
386
|
-
async function acquireFirstAvailableAccountAdmission(accountKeys, capacity, abortSignal, timeoutMs = MAX_TRANSIENT_QUEUE_WAIT_MS) {
|
|
387
|
-
const queuedAdmissions = [...new Set(accountKeys)].map((accountKey) => enqueueAccountAdmission(accountKey, capacity));
|
|
417
|
+
async function acquireFirstAvailableAccountAdmission(accountKeys, capacity, abortSignal, timeoutMs = MAX_TRANSIENT_QUEUE_WAIT_MS, generation) {
|
|
418
|
+
const queuedAdmissions = [...new Set(accountKeys)].map((accountKey) => enqueueAccountAdmission(accountKey, capacity, generation));
|
|
388
419
|
let winnerKey;
|
|
389
420
|
try {
|
|
390
421
|
return await withTimeout(raceWithAbort(Promise.race(queuedAdmissions.map((queued) => queued.promise.then((lease) => {
|
|
@@ -1475,81 +1506,17 @@ function accountSortMetrics(accountKey, now, sessionSoftLimit, sessionResetToler
|
|
|
1475
1506
|
weeklyUsedForSort: weeklyUsed ?? -1,
|
|
1476
1507
|
};
|
|
1477
1508
|
}
|
|
1478
|
-
function compareAccountRoutingFactors(a, b, metricsByKey, primaryKey) {
|
|
1479
|
-
const ma = metricsByKey.get(a.key);
|
|
1480
|
-
const mb = metricsByKey.get(b.key);
|
|
1481
|
-
if (!ma || !mb) {
|
|
1482
|
-
return [0, "insertion_order"];
|
|
1483
|
-
}
|
|
1484
|
-
if (ma.usable !== mb.usable) {
|
|
1485
|
-
return [ma.usable ? -1 : 1, "availability"];
|
|
1486
|
-
}
|
|
1487
|
-
if (!ma.usable && !mb.usable) {
|
|
1488
|
-
const au = ma.coolingUntil || Number.POSITIVE_INFINITY;
|
|
1489
|
-
const bu = mb.coolingUntil || Number.POSITIVE_INFINITY;
|
|
1490
|
-
return [
|
|
1491
|
-
au === bu ? 0 : au - bu,
|
|
1492
|
-
au === bu ? "insertion_order" : "cooldown_recovery",
|
|
1493
|
-
];
|
|
1494
|
-
}
|
|
1495
|
-
if (ma.quotaEvidenceRank !== mb.quotaEvidenceRank) {
|
|
1496
|
-
return [ma.quotaEvidenceRank - mb.quotaEvidenceRank, "quota_evidence"];
|
|
1497
|
-
}
|
|
1498
|
-
if (ma.saturated !== mb.saturated) {
|
|
1499
|
-
return [ma.saturated ? 1 : -1, "session_headroom"];
|
|
1500
|
-
}
|
|
1501
|
-
// Per-model headroom, after overall session capacity: an account whose cap
|
|
1502
|
-
// for THIS model is nearly spent is demoted even when its 5h/7d are healthy.
|
|
1503
|
-
// No-op when neither account reports a scoped window for the model.
|
|
1504
|
-
if (ma.scopedSaturated !== mb.scopedSaturated) {
|
|
1505
|
-
return [ma.scopedSaturated ? 1 : -1, "scoped_headroom"];
|
|
1506
|
-
}
|
|
1507
|
-
if (ma.saturated && mb.saturated) {
|
|
1508
|
-
if (ma.sessionResetBucket !== mb.sessionResetBucket) {
|
|
1509
|
-
return [ma.sessionResetBucket - mb.sessionResetBucket, "session_reset"];
|
|
1510
|
-
}
|
|
1511
|
-
if (ma.weeklyReset !== mb.weeklyReset) {
|
|
1512
|
-
return [ma.weeklyReset - mb.weeklyReset, "weekly_reset"];
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
else {
|
|
1516
|
-
if (ma.weeklyReset !== mb.weeklyReset) {
|
|
1517
|
-
return [ma.weeklyReset - mb.weeklyReset, "weekly_reset"];
|
|
1518
|
-
}
|
|
1519
|
-
if (ma.sessionResetBucket !== mb.sessionResetBucket) {
|
|
1520
|
-
return [ma.sessionResetBucket - mb.sessionResetBucket, "session_reset"];
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
// Fill-first within the per-model allowance: finish off the account closest
|
|
1524
|
-
// to spending its cap for this model before opening a fresher one. Ranked
|
|
1525
|
-
// above overall weekly utilization because it is the tighter constraint.
|
|
1526
|
-
// Both sides must actually report a scoped window. Comparing a real
|
|
1527
|
-
// utilization against the "absent" sentinel would rank the account that has a
|
|
1528
|
-
// window above one that does not — and since only the account serving a model
|
|
1529
|
-
// gets that model's window, it would funnel all of a model's traffic onto
|
|
1530
|
-
// whichever account happened to serve it first.
|
|
1531
|
-
if (ma.scopedUsed !== null &&
|
|
1532
|
-
mb.scopedUsed !== null &&
|
|
1533
|
-
ma.scopedUsedForSort !== mb.scopedUsedForSort) {
|
|
1534
|
-
return [mb.scopedUsedForSort - ma.scopedUsedForSort, "scoped_utilization"];
|
|
1535
|
-
}
|
|
1536
|
-
if (ma.weeklyUsedForSort !== mb.weeklyUsedForSort) {
|
|
1537
|
-
return [mb.weeklyUsedForSort - ma.weeklyUsedForSort, "weekly_utilization"];
|
|
1538
|
-
}
|
|
1539
|
-
if (primaryKey && (a.key === primaryKey) !== (b.key === primaryKey)) {
|
|
1540
|
-
return [a.key === primaryKey ? -1 : 1, "configured_primary"];
|
|
1541
|
-
}
|
|
1542
|
-
return [0, "insertion_order"];
|
|
1543
|
-
}
|
|
1544
1509
|
function orderAccountsByQuotaWithMetrics(accounts, now, primaryKey, sessionSoftLimit, sessionResetToleranceMs, requestedModel) {
|
|
1545
1510
|
const metricsByKey = new Map(accounts.map((account) => [
|
|
1546
1511
|
account.key,
|
|
1547
1512
|
accountSortMetrics(account.key, now, sessionSoftLimit, sessionResetToleranceMs, requestedModel),
|
|
1548
1513
|
]));
|
|
1549
|
-
|
|
1550
|
-
|
|
1514
|
+
const { orderedAccounts } = rankAccounts({
|
|
1515
|
+
accounts,
|
|
1551
1516
|
metricsByKey,
|
|
1552
|
-
|
|
1517
|
+
primaryKey,
|
|
1518
|
+
});
|
|
1519
|
+
return { orderedAccounts, metricsByKey };
|
|
1553
1520
|
}
|
|
1554
1521
|
/**
|
|
1555
1522
|
* Order accounts to MAXIMIZE quota utilization (fill-first, smart order):
|
|
@@ -1706,7 +1673,7 @@ function buildRoutingDecision(args) {
|
|
|
1706
1673
|
}
|
|
1707
1674
|
else if (quotaOrdered) {
|
|
1708
1675
|
mode = "quota";
|
|
1709
|
-
selectionReason =
|
|
1676
|
+
selectionReason = compareExpiryFirst(orderedAccounts[0], orderedAccounts[1], metricsByKey, primaryKey)[1];
|
|
1710
1677
|
}
|
|
1711
1678
|
else if (strategy === "round-robin") {
|
|
1712
1679
|
mode = "round_robin";
|
|
@@ -6783,7 +6750,7 @@ function buildDeferredClaudeAccountFailureResponse(args) {
|
|
|
6783
6750
|
return buildLoggedClaudeError(failure.status, failure.message, failure.errorType);
|
|
6784
6751
|
}
|
|
6785
6752
|
async function handleAnthropicRoutedClaudeRequest(args) {
|
|
6786
|
-
const { ctx, body, modelRouter, tracer, requestStartTime, accountStrategy, primaryAccountKey, accountAllowlist, quotaRoutingEnabled = isQuotaRoutingEnabled(), sessionSoftLimit = getSessionSoftLimit(), sessionResetToleranceMs = getSessionResetToleranceMs(), buildLoggedClaudeError, logProxyBody, logFinalRequest, setRoutingDecision, } = args;
|
|
6753
|
+
const { ctx, body, modelRouter, configGeneration, tracer, requestStartTime, accountStrategy, primaryAccountKey, accountAllowlist, quotaRoutingEnabled = isQuotaRoutingEnabled(), sessionSoftLimit = getSessionSoftLimit(), sessionResetToleranceMs = getSessionResetToleranceMs(), buildLoggedClaudeError, logProxyBody, logFinalRequest, setRoutingDecision, } = args;
|
|
6787
6754
|
const parsedRequest = parseClaudeRequest(body);
|
|
6788
6755
|
const configuredFallbackPlan = buildProxyTranslationPlan({ provider: "anthropic", model: body.model }, modelRouter?.getFallbackChain() ?? [], body.model, parsedRequest);
|
|
6789
6756
|
const hasConfiguredFallback = configuredFallbackPlan.attempts
|
|
@@ -6931,7 +6898,7 @@ async function handleAnthropicRoutedClaudeRequest(args) {
|
|
|
6931
6898
|
if (accountAdmissionCapacity !== undefined &&
|
|
6932
6899
|
effectiveAccounts.length > 0 &&
|
|
6933
6900
|
effectiveAccounts.every((account) => !isAccountAdmissionAvailable(account.key, accountAdmissionCapacity))) {
|
|
6934
|
-
queuedAccountAdmission = await acquireFirstAvailableAccountAdmission(effectiveAccounts.map((account) => account.key), accountAdmissionCapacity, ctx.abortSignal);
|
|
6901
|
+
queuedAccountAdmission = await acquireFirstAvailableAccountAdmission(effectiveAccounts.map((account) => account.key), accountAdmissionCapacity, ctx.abortSignal, MAX_TRANSIENT_QUEUE_WAIT_MS, configGeneration);
|
|
6935
6902
|
}
|
|
6936
6903
|
accountLoop: for (const [accountIndex, account,] of effectiveAccounts.entries()) {
|
|
6937
6904
|
const hasNextAccount = accountIndex < effectiveAccounts.length - 1;
|
|
@@ -7016,7 +6983,7 @@ async function handleAnthropicRoutedClaudeRequest(args) {
|
|
|
7016
6983
|
queuedAccountAdmission = undefined;
|
|
7017
6984
|
}
|
|
7018
6985
|
else {
|
|
7019
|
-
admissionLease = tryAcquireAccountAdmission(account.key, accountAdmissionCapacity);
|
|
6986
|
+
admissionLease = tryAcquireAccountAdmission(account.key, accountAdmissionCapacity, configGeneration);
|
|
7020
6987
|
if (admissionLease && queuedAccountAdmission) {
|
|
7021
6988
|
// A preferred account became available while the race was being
|
|
7022
6989
|
// established; release the lower-priority reservation.
|
|
@@ -7636,6 +7603,7 @@ export function createClaudeProxyRoutes(modelRouter, basePath = "", accountStrat
|
|
|
7636
7603
|
ctx,
|
|
7637
7604
|
body,
|
|
7638
7605
|
modelRouter: requestModelRouter,
|
|
7606
|
+
configGeneration: requestRouting.generation,
|
|
7639
7607
|
tracer,
|
|
7640
7608
|
requestStartTime,
|
|
7641
7609
|
accountStrategy: requestRouting.strategy,
|
|
@@ -8850,6 +8818,7 @@ export const __testHooks = {
|
|
|
8850
8818
|
getStreamFailureDetails,
|
|
8851
8819
|
trackUpstreamReadableStream,
|
|
8852
8820
|
orderAccountsByQuota,
|
|
8821
|
+
orderAccountsByQuotaWithMetrics,
|
|
8853
8822
|
scheduleAdaptiveQuotaRefreshes,
|
|
8854
8823
|
scheduleHandoffQuotaRefresh,
|
|
8855
8824
|
getQuotaRefreshState: (key) => accountQuotaRefreshCoordinator.getState(key),
|
|
@@ -8910,6 +8879,7 @@ export const __testHooks = {
|
|
|
8910
8879
|
acquireFirstAvailableAccountAdmission,
|
|
8911
8880
|
tryAcquireAccountAdmission,
|
|
8912
8881
|
enqueueAccountAdmission,
|
|
8882
|
+
getAccountInflight,
|
|
8913
8883
|
getAccountAdmissionSnapshot: (accountKey) => {
|
|
8914
8884
|
const state = accountAdmissionStates.get(accountKey);
|
|
8915
8885
|
return state
|
package/dist/types/cli.d.ts
CHANGED
|
@@ -405,6 +405,8 @@ export type CliGenerateResult = CommandResult & {
|
|
|
405
405
|
imageOutput?: {
|
|
406
406
|
base64: string;
|
|
407
407
|
savedPath?: string;
|
|
408
|
+
/** Encoded format, when the provider identified it (e.g. Recraft returns WebP). */
|
|
409
|
+
mimeType?: string;
|
|
408
410
|
} | null;
|
|
409
411
|
};
|
|
410
412
|
/**
|
|
@@ -10,7 +10,7 @@ import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
|
10
10
|
/**
|
|
11
11
|
* Supported MCP transport protocols - imported from mcpTypes.js (canonical definition)
|
|
12
12
|
*/
|
|
13
|
-
import type { MCPTransportType, MCPServerInfo } from "./mcp.js";
|
|
13
|
+
import type { MCPTransportType, MCPServerInfo, MCPServerReadiness } from "./mcp.js";
|
|
14
14
|
export type { MCPTransportType } from "./mcp.js";
|
|
15
15
|
/**
|
|
16
16
|
* External MCP server configuration for process spawning
|
|
@@ -182,10 +182,28 @@ export type ExternalMCPOperationResult<T = unknown> = {
|
|
|
182
182
|
serverId?: string;
|
|
183
183
|
/** Operation duration in milliseconds */
|
|
184
184
|
duration?: number;
|
|
185
|
-
/**
|
|
185
|
+
/**
|
|
186
|
+
* Additional metadata.
|
|
187
|
+
*
|
|
188
|
+
* The two typed optional fields are intersected with the pre-existing
|
|
189
|
+
* `JsonValue` index signature rather than declared inside it: declaring an
|
|
190
|
+
* optional property next to a `JsonValue` index signature does not compile
|
|
191
|
+
* (its type includes `undefined`), and widening the index signature to
|
|
192
|
+
* `JsonValue | undefined` would change the read type of every other key
|
|
193
|
+
* for every existing consumer — a backward-incompatible public change.
|
|
194
|
+
*/
|
|
186
195
|
metadata?: {
|
|
187
196
|
timestamp: number;
|
|
188
197
|
operation: string;
|
|
198
|
+
/**
|
|
199
|
+
* Set on `addServer` results: whether the registration discovered
|
|
200
|
+
* enough tools to be considered ready (see `MCPServerInfo.minTools`).
|
|
201
|
+
* Absent on operations the minTools gate does not apply to.
|
|
202
|
+
*/
|
|
203
|
+
readiness?: MCPServerReadiness;
|
|
204
|
+
/** Set alongside `readiness` on `addServer` results — tools discovered, post block-list. */
|
|
205
|
+
toolsDiscovered?: number;
|
|
206
|
+
} & {
|
|
189
207
|
[key: string]: JsonValue;
|
|
190
208
|
};
|
|
191
209
|
};
|
package/dist/types/generate.d.ts
CHANGED
|
@@ -954,9 +954,14 @@ export type MediaGenerationOutputs = {
|
|
|
954
954
|
* ```
|
|
955
955
|
*/
|
|
956
956
|
ppt?: PPTGenerationResult;
|
|
957
|
-
/**
|
|
957
|
+
/**
|
|
958
|
+
* Standard format for image generation. `mimeType` is set when the provider
|
|
959
|
+
* can identify the encoded format (sniffed from the image bytes, e.g.
|
|
960
|
+
* Recraft returns WebP), so callers do not have to assume PNG.
|
|
961
|
+
*/
|
|
958
962
|
imageOutput?: {
|
|
959
963
|
base64: string;
|
|
964
|
+
mimeType?: string;
|
|
960
965
|
} | null;
|
|
961
966
|
/** STT transcription result (present when stt.enabled is true and audio input was provided) */
|
|
962
967
|
transcription?: STTResult;
|
package/dist/types/mcp.d.ts
CHANGED
|
@@ -17,6 +17,13 @@ export type MCPTransportType = "stdio" | "sse" | "websocket" | "http" | "ws" | "
|
|
|
17
17
|
* MCP Server Connection Status - Individual server status
|
|
18
18
|
*/
|
|
19
19
|
export type MCPServerConnectionStatus = "initializing" | "connecting" | "connected" | "disconnected" | "failed" | "restarting" | "stopping" | "stopped";
|
|
20
|
+
/**
|
|
21
|
+
* Readiness of an external MCP server registration, distinct from raw
|
|
22
|
+
* connection status: a server can be "connected" at the transport level yet
|
|
23
|
+
* still be gated as not ready when it discovers fewer tools than its
|
|
24
|
+
* configured `minTools` floor.
|
|
25
|
+
*/
|
|
26
|
+
export type MCPServerReadiness = "ready" | "insufficient_tools" | "failed";
|
|
20
27
|
/**
|
|
21
28
|
* MCP Server Category Types - Deployment and server type classification
|
|
22
29
|
*/
|
|
@@ -56,6 +63,16 @@ export type MCPServerInfo = {
|
|
|
56
63
|
cwd?: string;
|
|
57
64
|
autoRestart?: boolean;
|
|
58
65
|
healthCheckInterval?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Minimum number of tools that must be discovered for this server's
|
|
68
|
+
* registration to be considered ready (default: 0 — no minimum, so a
|
|
69
|
+
* resource/prompt-only server that legitimately exposes zero tools still
|
|
70
|
+
* registers successfully). When discovery finds fewer tools than this
|
|
71
|
+
* floor, `ExternalServerManager.addServer` returns `success: false` with
|
|
72
|
+
* `metadata.readiness: "insufficient_tools"` instead of marking the
|
|
73
|
+
* server connected/healthy, and tears the connection back down.
|
|
74
|
+
*/
|
|
75
|
+
minTools?: number;
|
|
59
76
|
/** Retry configuration for HTTP transport */
|
|
60
77
|
retryConfig?: {
|
|
61
78
|
maxAttempts?: number;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type CatalogProviderName = "api-route" | "baseten" | "cerebras" | "cloudflare" | "fireworks" | "gmicloud" | "groq" | "inception-labs" | "io-intelligence" | "mancer" | "mistral" | "perplexity" | "sambanova" | "together-ai" | "upstage" | "xai";
|
|
2
|
-
export type CatalogCredentialKey = "apiRoute" | "baseten" | "cerebras" | "cloudflare" | "fireworks" | "gmicloud" | "groq" | "inceptionLabs" | "ioIntelligence" | "mancer" | "mistral" | "perplexity" | "sambanova" | "together" | "upstage" | "xai";
|
|
1
|
+
export type CatalogProviderName = "api-route" | "baseten" | "cerebras" | "cloudflare" | "fireworks" | "friendli" | "gmicloud" | "groq" | "inception-labs" | "io-intelligence" | "mancer" | "mistral" | "perplexity" | "sambanova" | "together-ai" | "upstage" | "xai";
|
|
2
|
+
export type CatalogCredentialKey = "apiRoute" | "baseten" | "cerebras" | "cloudflare" | "fireworks" | "friendli" | "gmicloud" | "groq" | "inceptionLabs" | "ioIntelligence" | "mancer" | "mistral" | "perplexity" | "sambanova" | "together" | "upstage" | "xai";
|
package/dist/types/proxy.d.ts
CHANGED
|
@@ -1100,6 +1100,9 @@ export type QueuedAccountAdmission = {
|
|
|
1100
1100
|
/** One queued request waiting for per-account admission capacity. */
|
|
1101
1101
|
export type AccountAdmissionWaiter = {
|
|
1102
1102
|
capacity: number;
|
|
1103
|
+
/** Runtime-config generation of the snapshot the request queued under;
|
|
1104
|
+
* absent when no runtime config store publishes one. */
|
|
1105
|
+
generation?: number;
|
|
1103
1106
|
resolve: (lease: AccountAdmissionLease) => void;
|
|
1104
1107
|
};
|
|
1105
1108
|
/** In-process request admission state for an OAuth account. */
|