Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/adapters/openai-responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -909,15 +909,24 @@ function stripStatefulResponsesParams(body: unknown): unknown {
* with `{"detail":"Unsupported parameter: …"}` (strict allowlist). Codex CLI never
* sends these — it controls output length via `reasoning.effort` — but third-party
* Responses API clients (GJC, SDK wrappers) include `max_output_tokens` per the
* public spec. `metadata` is likewise absent from the allowlist. No-op when the
* body carries neither field, keeping the common Codex path allocation-free.
* public spec. `metadata` is likewise absent from the allowlist. Codex can also
* send `prompt_cache_retention`, but the ChatGPT backend rejects it for models
* that do not expose extended retention instead of falling back to normal cache
* retention. No-op when the body carries none of these fields, keeping the common
* Codex path allocation-free. API-key Responses requests retain all three fields.
*/
function stripUnsupportedForwardParams(body: unknown): unknown {
if (!isPlainObject(body)) return body;
const hasMot = Object.prototype.hasOwnProperty.call(body, "max_output_tokens");
const hasMeta = Object.prototype.hasOwnProperty.call(body, "metadata");
if (!hasMot && !hasMeta) return body;
const { max_output_tokens: _mot, metadata: _meta, ...rest } = body;
const hasPromptCacheRetention = Object.prototype.hasOwnProperty.call(body, "prompt_cache_retention");
if (!hasMot && !hasMeta && !hasPromptCacheRetention) return body;
const {
max_output_tokens: _mot,
metadata: _meta,
prompt_cache_retention: _promptCacheRetention,
...rest
} = body;
return rest;
}

Expand Down
27 changes: 25 additions & 2 deletions tests/openai-responses-passthrough.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -804,8 +804,13 @@ describe("OpenAI Responses passthrough sanitization", () => {
expect(body.prompt_cache_key).toBe("project-cache-v1");
});

test("preserves prompt_cache_retention in the raw Responses passthrough body", () => {
const adapter = createResponsesPassthroughAdapter(provider);
test("preserves prompt_cache_retention for OpenAI API-key Responses requests", () => {
const adapter = createResponsesPassthroughAdapter({
adapter: "openai-responses",
baseUrl: "https://api.openai.com/v1",
authMode: "key",
apiKey: "sk-test",
});
const request = adapter.buildRequest({
modelId: "gpt-5.5",
context: { messages: [] },
Expand All @@ -822,6 +827,24 @@ describe("OpenAI Responses passthrough sanitization", () => {
expect(body.prompt_cache_retention).toBe("24h");
});

test("strips prompt_cache_retention from ChatGPT forward requests", () => {
const adapter = createResponsesPassthroughAdapter(provider);
const request = adapter.buildRequest({
modelId: "gpt-5.5",
context: { messages: [] },
stream: true,
options: {},
_rawBody: {
model: "gpt-5.5",
input: "hi",
prompt_cache_retention: "24h",
},
}, { headers: new Headers({ authorization: "Bearer token" }) });
const body = JSON.parse(request.body) as { prompt_cache_retention?: string };

expect(body).not.toHaveProperty("prompt_cache_retention");
});

const expandedRawBody = {
model: "gpt-5.5",
previous_response_id: "resp_1",
Expand Down
Loading