fix(openai): strip unsupported ChatGPT prompt cache retention options while preserving prompt cache keys

This commit is contained in:
2026-05-14 19:59:30 +00:00
parent 0e2053f538
commit 4725b55566
3 changed files with 34 additions and 10 deletions
+7
View File
@@ -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 ## 2026-05-14 - 4.0.1
### Fixes ### Fixes
+8
View File
@@ -203,6 +203,12 @@ tap.test('getModel uses ChatGPT Codex backend for OpenAI ChatGPT auth', async ()
model, model,
system: 'system prompt', system: 'system prompt',
prompt: 'hello', prompt: 'hello',
providerOptions: {
openai: {
promptCacheKey: 'session-1',
promptCacheRetention: 'in_memory',
},
},
}); });
expect(capturedRequest?.url).toEqual('https://chatgpt.com/backend-api/codex/responses'); 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([ expect(capturedBody.input).toEqual([
{ role: 'user', content: [{ type: 'input_text', text: 'hello' }] }, { role: 'user', content: [{ type: 'input_text', text: 'hello' }] },
]); ]);
expect(capturedBody.prompt_cache_key).toEqual('session-1');
expect(capturedBody.prompt_cache_retention).toEqual(undefined);
} finally { } finally {
globalThis.fetch = originalFetch; globalThis.fetch = originalFetch;
} }
+19 -10
View File
@@ -11,6 +11,10 @@ const getSystemInstructions = (prompt: LanguageModelV3CallOptions['prompt']): st
return instructions.length > 0 ? instructions.join('\n') : undefined; 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. * ChatGPT's Codex backend requires top-level Responses API instructions.
* The standard OpenAI provider otherwise serializes system prompts as input items. * The standard OpenAI provider otherwise serializes system prompts as input items.
@@ -20,25 +24,30 @@ export function createOpenAiChatGptInstructionsMiddleware(): LanguageModelV3Midd
specificationVersion: 'v3', specificationVersion: 'v3',
transformParams: async ({ params }) => { transformParams: async ({ params }) => {
const instructions = getSystemInstructions(params.prompt); 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; return params;
} }
const providerOptions = params.providerOptions ?? {}; const nextOpenAiProviderOptions: JSONObject = { ...openAiProviderOptions };
const openAiProviderOptions = providerOptions.openai ?? {}; delete nextOpenAiProviderOptions.promptCacheRetention;
if (isNonEmptyString(openAiProviderOptions.instructions)) { delete nextOpenAiProviderOptions.prompt_cache_retention;
return params; if (shouldApplyInstructions) {
nextOpenAiProviderOptions.instructions = instructions;
} }
return { return {
...params, ...params,
prompt: params.prompt.filter((message) => message.role !== 'system'), prompt: shouldApplyInstructions
? params.prompt.filter((message) => message.role !== 'system')
: params.prompt,
providerOptions: { providerOptions: {
...providerOptions, ...providerOptions,
openai: { openai: nextOpenAiProviderOptions,
...openAiProviderOptions,
instructions,
} as JSONObject,
}, },
} satisfies LanguageModelV3CallOptions; } satisfies LanguageModelV3CallOptions;
}, },