fix(ai): clamp OpenAI prompt cache keys

closes #4720
This commit is contained in:
Mario Zechner
2026-05-19 10:51:11 +02:00
parent 725e2b7b2a
commit 7be75baded
10 changed files with 128 additions and 5 deletions

View File

@@ -13,6 +13,7 @@ import type {
} from "../types.js";
import { AssistantMessageEventStream } from "../utils/event-stream.js";
import { headersToRecord } from "../utils/headers.js";
import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
import { buildBaseOptions } from "./simple-options.js";
@@ -261,7 +262,7 @@ function buildParams(
model: deploymentName,
input: messages,
stream: true,
prompt_cache_key: options?.sessionId,
prompt_cache_key: clampOpenAIPromptCacheKey(options?.sessionId),
};
if (options?.maxTokens) {

View File

@@ -40,6 +40,7 @@ import {
} from "../utils/diagnostics.js";
import { AssistantMessageEventStream } from "../utils/event-stream.js";
import { headersToRecord } from "../utils/headers.js";
import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
import { buildBaseOptions } from "./simple-options.js";
@@ -378,7 +379,7 @@ function buildRequestBody(
input: messages,
text: { verbosity: options?.textVerbosity || "low" },
include: ["reasoning.encrypted_content"],
prompt_cache_key: options?.sessionId,
prompt_cache_key: clampOpenAIPromptCacheKey(options?.sessionId),
tool_choice: "auto",
parallel_tool_calls: true,
};

View File

@@ -36,6 +36,7 @@ import { parseStreamingJson } from "../utils/json-parse.js";
import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
import { isCloudflareProvider, resolveCloudflareBaseUrl } from "./cloudflare.js";
import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
import { buildBaseOptions } from "./simple-options.js";
import { transformMessages } from "./transform-messages.js";
@@ -516,7 +517,7 @@ function buildParams(
prompt_cache_key:
(model.baseUrl.includes("api.openai.com") && cacheRetention !== "none") ||
(cacheRetention === "long" && compat.supportsLongCacheRetention)
? options?.sessionId
? clampOpenAIPromptCacheKey(options?.sessionId)
: undefined,
prompt_cache_retention: cacheRetention === "long" && compat.supportsLongCacheRetention ? "24h" : undefined,
};

View File

@@ -0,0 +1,8 @@
export const OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH = 64;
export function clampOpenAIPromptCacheKey(key: string | undefined): string | undefined {
if (key === undefined) return undefined;
const chars = Array.from(key);
if (chars.length <= OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH) return key;
return chars.slice(0, OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH).join("");
}

View File

@@ -18,6 +18,7 @@ import { AssistantMessageEventStream } from "../utils/event-stream.js";
import { headersToRecord } from "../utils/headers.js";
import { isCloudflareProvider, resolveCloudflareBaseUrl } from "./cloudflare.js";
import { buildCopilotDynamicHeaders, hasCopilotVisionInput } from "./github-copilot-headers.js";
import { clampOpenAIPromptCacheKey } from "./openai-prompt-cache.js";
import { convertResponsesMessages, convertResponsesTools, processResponsesStream } from "./openai-responses-shared.js";
import { buildBaseOptions } from "./simple-options.js";
@@ -240,7 +241,7 @@ function buildParams(model: Model<"openai-responses">, context: Context, options
model: model.id,
input: messages,
stream: true,
prompt_cache_key: cacheRetention === "none" ? undefined : options?.sessionId,
prompt_cache_key: cacheRetention === "none" ? undefined : clampOpenAIPromptCacheKey(options?.sessionId),
prompt_cache_retention: getPromptCacheRetention(compat, cacheRetention),
store: false,
};