From aa2484f83c422565307c44de48203deb09f29b84 Mon Sep 17 00:00:00 2001 From: Felix-Hz Date: Mon, 27 Apr 2026 16:23:56 +1200 Subject: [PATCH] fix(opencode): prevent negative cost when cache tokens exceed input --- packages/opencode/src/session/session.ts | 2 +- .../opencode/test/session/compaction.test.ts | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/session/session.ts b/packages/opencode/src/session/session.ts index 6c67b8517e9f..444ba07d4736 100644 --- a/packages/opencode/src/session/session.ts +++ b/packages/opencode/src/session/session.ts @@ -298,7 +298,7 @@ export function plan(input: { slug: string; time: { created: number } }) { export const getUsage = (input: { model: Provider.Model; usage: LanguageModelUsage; metadata?: ProviderMetadata }) => { const safe = (value: number) => { - if (!Number.isFinite(value)) return 0 + if (!Number.isFinite(value) || value < 0) return 0 return value } const inputTokens = safe(input.usage.inputTokens ?? 0) diff --git a/packages/opencode/test/session/compaction.test.ts b/packages/opencode/test/session/compaction.test.ts index 1b2b120b6164..51574c785a77 100644 --- a/packages/opencode/test/session/compaction.test.ts +++ b/packages/opencode/test/session/compaction.test.ts @@ -2089,6 +2089,34 @@ describe("SessionNs.getUsage", () => { expect(result.cost).toBe(3 + 1.5) }) + test("does not return negative cost when cache tokens exceed input tokens", () => { + const model = createModel({ + context: 100_000, + output: 32_000, + cost: { input: 10, output: 0, cache: { read: 0, write: 0 } }, + }) + const result = SessionNs.getUsage({ + model, + usage: { + inputTokens: 100, + outputTokens: 50, + totalTokens: 150, + inputTokenDetails: { + noCacheTokens: undefined, + cacheReadTokens: 200, + cacheWriteTokens: undefined, + }, + outputTokenDetails: { + textTokens: undefined, + reasoningTokens: undefined, + }, + }, + }) + + expect(result.tokens.input).toBe(0) + expect(result.cost).toBe(0) + }) + test.each(["@ai-sdk/anthropic", "@ai-sdk/amazon-bedrock", "@ai-sdk/google-vertex/anthropic"])( "computes total from components for %s models", (npm) => {