From 4725b55566e0812baf03046a711da35f4121f0bf Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Thu, 14 May 2026 19:59:30 +0000 Subject: [PATCH] fix(openai): strip unsupported ChatGPT prompt cache retention options while preserving prompt cache keys --- changelog.md | 7 +++++++ test/test.openai-auth.node.ts | 8 ++++++++ ts/smartai.middleware.openai.ts | 29 +++++++++++++++++++---------- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index 7085741..6803529 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,13 @@ +### Fixes + +- strip unsupported ChatGPT prompt cache retention options while preserving prompt cache keys (openai) + - Removes promptCacheRetention values before sending requests to the ChatGPT Codex backend. + - Keeps prompt_cache_key forwarding intact for OpenAI provider options. + - Only rewrites system prompts into top-level instructions when needed, avoiding unnecessary prompt changes. + ## 2026-05-14 - 4.0.1 ### Fixes diff --git a/test/test.openai-auth.node.ts b/test/test.openai-auth.node.ts index 3b45163..93e2e3d 100644 --- a/test/test.openai-auth.node.ts +++ b/test/test.openai-auth.node.ts @@ -203,6 +203,12 @@ tap.test('getModel uses ChatGPT Codex backend for OpenAI ChatGPT auth', async () model, system: 'system prompt', prompt: 'hello', + providerOptions: { + openai: { + promptCacheKey: 'session-1', + promptCacheRetention: 'in_memory', + }, + }, }); expect(capturedRequest?.url).toEqual('https://chatgpt.com/backend-api/codex/responses'); @@ -214,6 +220,8 @@ tap.test('getModel uses ChatGPT Codex backend for OpenAI ChatGPT auth', async () expect(capturedBody.input).toEqual([ { role: 'user', content: [{ type: 'input_text', text: 'hello' }] }, ]); + expect(capturedBody.prompt_cache_key).toEqual('session-1'); + expect(capturedBody.prompt_cache_retention).toEqual(undefined); } finally { globalThis.fetch = originalFetch; } diff --git a/ts/smartai.middleware.openai.ts b/ts/smartai.middleware.openai.ts index 0af1d59..6c32ec7 100644 --- a/ts/smartai.middleware.openai.ts +++ b/ts/smartai.middleware.openai.ts @@ -11,6 +11,10 @@ const getSystemInstructions = (prompt: LanguageModelV3CallOptions['prompt']): st return instructions.length > 0 ? instructions.join('\n') : undefined; }; +const hasUnsupportedChatGptCacheRetention = (options: JSONObject): boolean => { + return options.promptCacheRetention !== undefined || options.prompt_cache_retention !== undefined; +}; + /** * ChatGPT's Codex backend requires top-level Responses API instructions. * The standard OpenAI provider otherwise serializes system prompts as input items. @@ -20,25 +24,30 @@ export function createOpenAiChatGptInstructionsMiddleware(): LanguageModelV3Midd specificationVersion: 'v3', transformParams: async ({ params }) => { const instructions = getSystemInstructions(params.prompt); - if (!instructions) { + const providerOptions = params.providerOptions ?? {}; + const openAiProviderOptions = providerOptions.openai ?? {}; + const shouldApplyInstructions = !!instructions && !isNonEmptyString(openAiProviderOptions.instructions); + const shouldStripCacheRetention = hasUnsupportedChatGptCacheRetention(openAiProviderOptions); + + if (!shouldApplyInstructions && !shouldStripCacheRetention) { return params; } - const providerOptions = params.providerOptions ?? {}; - const openAiProviderOptions = providerOptions.openai ?? {}; - if (isNonEmptyString(openAiProviderOptions.instructions)) { - return params; + const nextOpenAiProviderOptions: JSONObject = { ...openAiProviderOptions }; + delete nextOpenAiProviderOptions.promptCacheRetention; + delete nextOpenAiProviderOptions.prompt_cache_retention; + if (shouldApplyInstructions) { + nextOpenAiProviderOptions.instructions = instructions; } return { ...params, - prompt: params.prompt.filter((message) => message.role !== 'system'), + prompt: shouldApplyInstructions + ? params.prompt.filter((message) => message.role !== 'system') + : params.prompt, providerOptions: { ...providerOptions, - openai: { - ...openAiProviderOptions, - instructions, - } as JSONObject, + openai: nextOpenAiProviderOptions, }, } satisfies LanguageModelV3CallOptions; },