feat(providers): let custom connections opt into prompt-cache capability (#6880) (#7257)

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:
Diego Rodrigues de Sa e Souza
2026-07-17 10:41:09 -03:00
committed by GitHub
parent 98966fdac9
commit 6c8392fa45
10 changed files with 393 additions and 25 deletions

View File

@@ -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;

View File

@@ -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({