feat: update pricing schema for models to ensure more accurate cost tracking (#27184)

This commit is contained in:
Aiden Cline
2026-05-12 20:44:06 -05:00
committed by GitHub
parent d1356f509e
commit c2b1ebd9dc
6 changed files with 114570 additions and 62322 deletions

View File

@@ -1758,6 +1758,101 @@ describe("SessionNs.getUsage", () => {
expect(result.cost).toBe(3 + 1.5)
})
test("uses matching context cost tier before over-200k fallback", () => {
const model = createModel({
context: 1_000_000,
output: 32_000,
cost: {
input: 1,
output: 2,
cache: { read: 0.1, write: 0.5 },
tiers: [
{
input: 3,
output: 4,
cache: { read: 0.3, write: 1.5 },
tier: { type: "context", size: 200_000 },
},
{
input: 5,
output: 6,
cache: { read: 0.5, write: 2.5 },
tier: { type: "context", size: 500_000 },
},
],
experimentalOver200K: {
input: 100,
output: 100,
cache: { read: 100, write: 100 },
},
},
})
const result = SessionNs.getUsage({
model,
usage: {
inputTokens: 650_000,
outputTokens: 100_000,
totalTokens: 750_000,
inputTokenDetails: {
noCacheTokens: undefined,
cacheReadTokens: 100_000,
cacheWriteTokens: undefined,
},
outputTokenDetails: {
textTokens: undefined,
reasoningTokens: undefined,
},
},
})
expect(result.tokens.input).toBe(550_000)
expect(result.cost).toBe(2.75 + 0.6 + 0.05)
})
test("falls back to over-200k pricing when no cost tier matches", () => {
const model = createModel({
context: 1_000_000,
output: 32_000,
cost: {
input: 1,
output: 2,
cache: { read: 0.1, write: 0.5 },
tiers: [
{
input: 5,
output: 6,
cache: { read: 0.5, write: 2.5 },
tier: { type: "context", size: 500_000 },
},
],
experimentalOver200K: {
input: 3,
output: 4,
cache: { read: 0.3, write: 1.5 },
},
},
})
const result = SessionNs.getUsage({
model,
usage: {
inputTokens: 300_000,
outputTokens: 100_000,
totalTokens: 400_000,
inputTokenDetails: {
noCacheTokens: undefined,
cacheReadTokens: undefined,
cacheWriteTokens: undefined,
},
outputTokenDetails: {
textTokens: undefined,
reasoningTokens: undefined,
},
},
})
expect(result.cost).toBe(0.9 + 0.4)
})
test.each(["@ai-sdk/anthropic", "@ai-sdk/amazon-bedrock", "@ai-sdk/google-vertex/anthropic"])(
"computes total from components for %s models",
(npm) => {

View File

@@ -277,6 +277,25 @@ async function loadFixture(providerID: string, modelID: string) {
return { provider, model }
}
function configModel(model: ModelsDev.Model) {
return {
id: model.id,
name: model.name,
family: model.family,
release_date: model.release_date,
attachment: model.attachment,
reasoning: model.reasoning,
temperature: model.temperature,
tool_call: model.tool_call,
interleaved: model.interleaved,
cost: model.cost ? { ...model.cost, tiers: undefined } : undefined,
limit: model.limit,
modalities: model.modalities,
status: model.status,
provider: model.provider,
}
}
function createEventStream(chunks: unknown[], includeDone = false) {
const lines = chunks.map((chunk) => `data: ${typeof chunk === "string" ? chunk : JSON.stringify(chunk)}`)
if (includeDone) {
@@ -617,7 +636,7 @@ describe("session.llm.stream", () => {
npm: "@ai-sdk/openai",
api: "https://api.openai.com/v1",
models: {
[model.id]: model,
[model.id]: configModel(model),
},
options: {
apiKey: "test-openai-key",
@@ -733,7 +752,7 @@ describe("session.llm.stream", () => {
npm: "@ai-sdk/openai",
api: "https://api.openai.com/v1",
models: {
[model.id]: model,
[model.id]: configModel(model),
},
options: {
apiKey: "test-openai-key",
@@ -970,7 +989,7 @@ describe("session.llm.stream", () => {
npm: "@ai-sdk/anthropic",
api: "https://api.anthropic.com/v1",
models: {
[model.id]: model,
[model.id]: configModel(model),
},
options: {
apiKey: "test-anthropic-key",

File diff suppressed because it is too large Load Diff