diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index ccd3c55b4f1..69031bcc0fc 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -775,7 +775,7 @@ export namespace Provider { input: model.cost?.input ?? 0, output: model.cost?.output ?? 0, cache: { - read: model.cost?.cache_read ?? 0, + read: model.cost?.cache_read ?? model.cost?.input ?? 0, write: model.cost?.cache_write ?? 0, }, experimentalOver200K: model.cost?.context_over_200k @@ -947,7 +947,12 @@ export namespace Provider { input: model?.cost?.input ?? existingModel?.cost?.input ?? 0, output: model?.cost?.output ?? existingModel?.cost?.output ?? 0, cache: { - read: model?.cost?.cache_read ?? existingModel?.cost?.cache.read ?? 0, + read: + model?.cost?.cache_read ?? + existingModel?.cost?.cache.read ?? + model?.cost?.input ?? + existingModel?.cost?.input ?? + 0, write: model?.cost?.cache_write ?? existingModel?.cost?.cache.write ?? 0, }, }, diff --git a/packages/opencode/test/provider/provider.test.ts b/packages/opencode/test/provider/provider.test.ts index 4c6eaf8b227..ab34f5741da 100644 --- a/packages/opencode/test/provider/provider.test.ts +++ b/packages/opencode/test/provider/provider.test.ts @@ -492,6 +492,98 @@ test("model cost defaults to zero when not specified", async () => { }) }) +test("cache read cost falls back to input cost when not specified", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + await Bun.write( + path.join(dir, "opencode.json"), + JSON.stringify({ + $schema: "https://opencode.ai/config.json", + provider: { + "test-provider": { + name: "Test Provider", + npm: "@ai-sdk/openai-compatible", + env: [], + models: { + "test-model": { + name: "Test Model", + tool_call: true, + limit: { context: 128000, output: 4096 }, + cost: { + input: 5, + output: 15, + }, + }, + }, + options: { + apiKey: "test-key", + }, + }, + }, + }), + ) + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const providers = await Provider.list() + const model = providers["test-provider"].models["test-model"] + expect(model.cost.input).toBe(5) + expect(model.cost.output).toBe(15) + expect(model.cost.cache.read).toBe(5) + expect(model.cost.cache.write).toBe(0) + }, + }) +}) + +test("cache read cost uses explicit value when provided", async () => { + await using tmp = await tmpdir({ + init: async (dir) => { + await Bun.write( + path.join(dir, "opencode.json"), + JSON.stringify({ + $schema: "https://opencode.ai/config.json", + provider: { + "test-provider": { + name: "Test Provider", + npm: "@ai-sdk/openai-compatible", + env: [], + models: { + "test-model": { + name: "Test Model", + tool_call: true, + limit: { context: 128000, output: 4096 }, + cost: { + input: 5, + output: 15, + cache_read: 1, + cache_write: 2, + }, + }, + }, + options: { + apiKey: "test-key", + }, + }, + }, + }), + ) + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const providers = await Provider.list() + const model = providers["test-provider"].models["test-model"] + expect(model.cost.input).toBe(5) + expect(model.cost.output).toBe(15) + expect(model.cost.cache.read).toBe(1) + expect(model.cost.cache.write).toBe(2) + }, + }) +}) + test("model options are merged from existing model", async () => { await using tmp = await tmpdir({ init: async (dir) => {