mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-08 00:02:20 +03:00
Add a per-connection cache capability override (supportsPromptCaching, cacheControlPassthrough) stored in provider_specific_data.cache, consulted first by providerSupportsCaching() / providerHonorsOpenAIFormatCacheControl() before falling back to the hardcoded CACHING_PROVIDERS name sets. Unblocks prompt_cache_key injection, the compression cache-aware guard, and cache_control passthrough for openai-compatible-chat-<uuid>-style custom connections that can never match the hardcoded provider-name sets. Default (no override) is byte-identical to current behavior.
This commit is contained in:
committed by
GitHub
parent
98966fdac9
commit
6c8392fa45
@@ -129,6 +129,54 @@ export function normalizeRequestDefaults(
|
||||
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
||||
}
|
||||
|
||||
const CACHE_PASSTHROUGH_VALUES = new Set(["strip", "openai-format", "claude-format"]);
|
||||
|
||||
// #6880 — per-connection prompt-cache capability override: strip unknown keys / invalid
|
||||
// types, drop the sub-object entirely when nothing valid survives.
|
||||
export function normalizeCacheOverride(value: unknown): JsonRecord | undefined {
|
||||
const record = asRecord(value);
|
||||
if (Object.keys(record).length === 0) return undefined;
|
||||
|
||||
const normalized: JsonRecord = {};
|
||||
if (typeof record.supportsPromptCaching === "boolean") {
|
||||
normalized.supportsPromptCaching = record.supportsPromptCaching;
|
||||
}
|
||||
if (
|
||||
typeof record.cacheControlPassthrough === "string" &&
|
||||
CACHE_PASSTHROUGH_VALUES.has(record.cacheControlPassthrough)
|
||||
) {
|
||||
normalized.cacheControlPassthrough = record.cacheControlPassthrough;
|
||||
}
|
||||
|
||||
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
||||
}
|
||||
|
||||
// #6880 — extracted so normalizeProviderSpecificData() stays under the
|
||||
// max-lines-per-function gate: normalizes the two nested-object sub-fields
|
||||
// (requestDefaults, cache) in one pass.
|
||||
function normalizeNestedSubObjects(
|
||||
provider: string | null | undefined,
|
||||
normalized: JsonRecord
|
||||
): void {
|
||||
if ("requestDefaults" in normalized) {
|
||||
const requestDefaults = normalizeRequestDefaults(provider, normalized.requestDefaults);
|
||||
if (requestDefaults) {
|
||||
normalized.requestDefaults = requestDefaults;
|
||||
} else {
|
||||
delete normalized.requestDefaults;
|
||||
}
|
||||
}
|
||||
|
||||
if ("cache" in normalized) {
|
||||
const cache = normalizeCacheOverride(normalized.cache);
|
||||
if (cache) {
|
||||
normalized.cache = cache;
|
||||
} else {
|
||||
delete normalized.cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeProviderSpecificData(
|
||||
provider: string | null | undefined,
|
||||
value: unknown
|
||||
@@ -138,14 +186,7 @@ export function normalizeProviderSpecificData(
|
||||
|
||||
const normalized: JsonRecord = { ...record };
|
||||
|
||||
if ("requestDefaults" in normalized) {
|
||||
const requestDefaults = normalizeRequestDefaults(provider, normalized.requestDefaults);
|
||||
if (requestDefaults) {
|
||||
normalized.requestDefaults = requestDefaults;
|
||||
} else {
|
||||
delete normalized.requestDefaults;
|
||||
}
|
||||
}
|
||||
normalizeNestedSubObjects(provider, normalized);
|
||||
|
||||
if ("openaiStoreEnabled" in normalized && typeof normalized.openaiStoreEnabled !== "boolean") {
|
||||
delete normalized.openaiStoreEnabled;
|
||||
|
||||
@@ -15,6 +15,44 @@ function isHttpUrl(value: string): boolean {
|
||||
|
||||
const CODEX_REASONING_EFFORT_VALUES = new Set(["none", "low", "medium", "high", "xhigh", "max"]);
|
||||
const REQUEST_DEFAULT_SERVICE_TIER_VALUES = new Set(["default", "priority", "fast", "flex"]);
|
||||
const CACHE_PASSTHROUGH_VALUES = new Set(["strip", "openai-format", "claude-format"]);
|
||||
|
||||
// #6880 — per-connection prompt-cache capability override, extracted so
|
||||
// validateProviderSpecificData() stays under the complexity gate.
|
||||
function validateCacheBlock(data: Record<string, unknown>, ctx: z.RefinementCtx): void {
|
||||
const cache = data.cache;
|
||||
if (cache === undefined) return;
|
||||
if (!cache || typeof cache !== "object" || Array.isArray(cache)) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "providerSpecificData.cache must be an object",
|
||||
path: ["cache"],
|
||||
});
|
||||
return;
|
||||
}
|
||||
const cacheRecord = cache as Record<string, unknown>;
|
||||
const supportsPromptCaching = cacheRecord.supportsPromptCaching;
|
||||
if (supportsPromptCaching !== undefined && typeof supportsPromptCaching !== "boolean") {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "providerSpecificData.cache.supportsPromptCaching must be a boolean",
|
||||
path: ["cache", "supportsPromptCaching"],
|
||||
});
|
||||
}
|
||||
const cacheControlPassthrough = cacheRecord.cacheControlPassthrough;
|
||||
if (
|
||||
cacheControlPassthrough !== undefined &&
|
||||
(typeof cacheControlPassthrough !== "string" ||
|
||||
!CACHE_PASSTHROUGH_VALUES.has(cacheControlPassthrough))
|
||||
) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message:
|
||||
'providerSpecificData.cache.cacheControlPassthrough must be one of "strip", "openai-format", "claude-format"',
|
||||
path: ["cache", "cacheControlPassthrough"],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function validateProviderSpecificData(
|
||||
data: Record<string, unknown> | undefined,
|
||||
@@ -163,6 +201,8 @@ export function validateProviderSpecificData(
|
||||
}
|
||||
}
|
||||
|
||||
validateCacheBlock(data, ctx);
|
||||
|
||||
const consoleApiKey = data.consoleApiKey;
|
||||
if (consoleApiKey !== undefined && consoleApiKey !== null && typeof consoleApiKey !== "string") {
|
||||
ctx.addIssue({
|
||||
|
||||
Reference in New Issue
Block a user