From 2e5199a40d8791e99dc304ad722bf6baa707f09c Mon Sep 17 00:00:00 2001 From: chrarnoldus <12196001+chrarnoldus@users.noreply.github.com> Date: Mon, 10 Aug 2026 12:49:48 +0000 Subject: [PATCH] feat(cli): exclude ChatGPT subscriptions from explicit prompt cache breakpoints --- ...de-chatgpt-from-prompt-cache-breakpoint.md | 5 ++ packages/opencode/src/provider/transform.ts | 19 ++++-- .../opencode/test/provider/transform.test.ts | 64 +++++++++++++++++++ 3 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 .changeset/exclude-chatgpt-from-prompt-cache-breakpoint.md diff --git a/.changeset/exclude-chatgpt-from-prompt-cache-breakpoint.md b/.changeset/exclude-chatgpt-from-prompt-cache-breakpoint.md new file mode 100644 index 00000000000..6362bdd7ff1 --- /dev/null +++ b/.changeset/exclude-chatgpt-from-prompt-cache-breakpoint.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Exclude ChatGPT subscriptions from explicit prompt cache breakpoints. diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index ff534bf107f..7a9659b25d2 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -328,15 +328,22 @@ function normalizeMessages( return msgs } -// kilocode_change start - explicit prompt cache breakpoints for GPT-5.6+ -function supportsPromptCacheBreakpoint(modelId: string): boolean { - const match = modelId.match(/gpt-(\d+)\.(\d+)/) +// kilocode_change start - explicit prompt cache breakpoints for GPT-5.6+ (excluding ChatGPT subscriptions) +function isChatGPTSubscription(model: Provider.Model): boolean { + if (model.providerID === "openai" && model.cost?.input === 0 && model.cost?.output === 0) return true + if (typeof model.api.url === "string" && model.api.url.includes("chatgpt.com")) return true + return false +} + +function supportsPromptCacheBreakpoint(model: Provider.Model): boolean { + if (isChatGPTSubscription(model)) return false + const match = model.api.id.match(/gpt-(\d+)\.(\d+)/) if (match) { const major = Number(match[1]) const minor = Number(match[2]) if (major > 5 || (major === 5 && minor >= 6)) return true } - const majorMatch = modelId.match(/gpt-(\d+)/) + const majorMatch = model.api.id.match(/gpt-(\d+)/) if (majorMatch && Number(majorMatch[1]) >= 6) return true return false } @@ -366,7 +373,7 @@ function applyCaching(msgs: ModelMessage[], model: Provider.Model): ModelMessage cacheControl: { type: "ephemeral" }, }, // kilocode_change start - ...(supportsPromptCacheBreakpoint(model.api.id) + ...(supportsPromptCacheBreakpoint(model) ? { openai: { promptCacheBreakpoint: { mode: "explicit" }, @@ -494,7 +501,7 @@ export function message(msgs: ModelMessage[], model: Provider.Model, options: Re ((model.api.npm === "@ai-sdk/openai" || model.api.npm === "@ai-sdk/azure" || model.api.npm === "@kilocode/kilo-gateway") && - supportsPromptCacheBreakpoint(model.api.id))) && + supportsPromptCacheBreakpoint(model))) && model.api.npm !== "@ai-sdk/gateway" ) { msgs = applyCaching(msgs, model) diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 74ef174ade8..508f6a8cd0b 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -3162,6 +3162,70 @@ describe("ProviderTransform.message - cache control on gateway", () => { }, }) }) + + test("openai gpt-5.6 with ChatGPT subscription (zero cost) does not apply promptCacheBreakpoint", () => { + const model = createModel({ + providerID: "openai", + api: { + id: "gpt-5.6", + url: "https://api.openai.com/v1", + npm: "@ai-sdk/openai", + }, + id: "gpt-5.6", + cost: { + input: 0, + output: 0, + cache: { read: 0, write: 0 }, + }, + }) + const msgs = [ + { + role: "system", + content: "You are a helpful assistant", + }, + { + role: "user", + content: "Hello", + }, + ] as any[] + + const result = ProviderTransform.message(msgs, model, {}) as any[] + + expect(result[0].providerOptions?.openai?.promptCacheBreakpoint).toBeUndefined() + expect(result[1].providerOptions?.openai?.promptCacheBreakpoint).toBeUndefined() + }) + + test("openai gpt-5.6 with ChatGPT backend endpoint does not apply promptCacheBreakpoint", () => { + const model = createModel({ + providerID: "openai", + api: { + id: "gpt-5.6", + url: "https://chatgpt.com/backend-api/codex/responses", + npm: "@ai-sdk/openai", + }, + id: "gpt-5.6", + cost: { + input: 0.002, + output: 0.008, + cache: { read: 0.0005, write: 0.002 }, + }, + }) + const msgs = [ + { + role: "system", + content: "You are a helpful assistant", + }, + { + role: "user", + content: "Hello", + }, + ] as any[] + + const result = ProviderTransform.message(msgs, model, {}) as any[] + + expect(result[0].providerOptions?.openai?.promptCacheBreakpoint).toBeUndefined() + expect(result[1].providerOptions?.openai?.promptCacheBreakpoint).toBeUndefined() + }) // kilocode_change end })