From 26cc924ea223cb27449b432beddb8abcfc36e65b Mon Sep 17 00:00:00 2001 From: Major Hayden Date: Tue, 31 Mar 2026 15:16:14 -0500 Subject: [PATCH] feat: enable prompt caching and cache token tracking for google-vertex-anthropic (#20266) Signed-off-by: Major Hayden --- packages/opencode/src/provider/transform.ts | 1 + packages/opencode/src/session/index.ts | 3 ++ .../opencode/test/provider/transform.test.ts | 52 +++++++++++++++++++ .../opencode/test/session/compaction.test.ts | 22 ++++++++ 4 files changed, 78 insertions(+) diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index 219200b765..c402238685 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -280,6 +280,7 @@ export namespace ProviderTransform { msgs = normalizeMessages(msgs, model, options) if ( (model.providerID === "anthropic" || + model.providerID === "google-vertex-anthropic" || model.api.id.includes("anthropic") || model.api.id.includes("claude") || model.id.includes("anthropic") || diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 74506c31da..94aee14c09 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -257,6 +257,9 @@ export namespace Session { const cacheReadInputTokens = safe(input.usage.cachedInputTokens ?? 0) const cacheWriteInputTokens = safe( (input.metadata?.["anthropic"]?.["cacheCreationInputTokens"] ?? + // google-vertex-anthropic returns metadata under "vertex" key + // (AnthropicMessagesLanguageModel custom provider key from 'vertex.anthropic.messages') + input.metadata?.["vertex"]?.["cacheCreationInputTokens"] ?? // @ts-expect-error input.metadata?.["bedrock"]?.["usage"]?.["cacheWriteInputTokens"] ?? // @ts-expect-error diff --git a/packages/opencode/test/provider/transform.test.ts b/packages/opencode/test/provider/transform.test.ts index 5a1016bb7d..0aee396f44 100644 --- a/packages/opencode/test/provider/transform.test.ts +++ b/packages/opencode/test/provider/transform.test.ts @@ -1792,6 +1792,58 @@ describe("ProviderTransform.message - cache control on gateway", () => { }, }) }) + + test("google-vertex-anthropic applies cache control", () => { + const model = createModel({ + providerID: "google-vertex-anthropic", + api: { + id: "google-vertex-anthropic", + url: "https://us-central1-aiplatform.googleapis.com", + npm: "@ai-sdk/google-vertex/anthropic", + }, + id: "claude-sonnet-4@20250514", + }) + 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).toEqual({ + anthropic: { + cacheControl: { + type: "ephemeral", + }, + }, + openrouter: { + cacheControl: { + type: "ephemeral", + }, + }, + bedrock: { + cachePoint: { + type: "default", + }, + }, + openaiCompatible: { + cache_control: { + type: "ephemeral", + }, + }, + copilot: { + copilot_cache_control: { + type: "ephemeral", + }, + }, + }) + }) }) describe("ProviderTransform.variants", () => { diff --git a/packages/opencode/test/session/compaction.test.ts b/packages/opencode/test/session/compaction.test.ts index a686d7ccff..e6d715728d 100644 --- a/packages/opencode/test/session/compaction.test.ts +++ b/packages/opencode/test/session/compaction.test.ts @@ -1199,4 +1199,26 @@ describe("session.getUsage", () => { expect(result.tokens.total).toBe(1500) }, ) + + test("extracts cache write tokens from vertex metadata key", () => { + const model = createModel({ context: 100_000, output: 32_000, npm: "@ai-sdk/google-vertex/anthropic" }) + const result = Session.getUsage({ + model, + usage: { + inputTokens: 1000, + outputTokens: 500, + totalTokens: 1500, + cachedInputTokens: 200, + }, + metadata: { + vertex: { + cacheCreationInputTokens: 300, + }, + }, + }) + + expect(result.tokens.input).toBe(500) + expect(result.tokens.cache.read).toBe(200) + expect(result.tokens.cache.write).toBe(300) + }) })