mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 02:47:45 +08:00
fix(models): correct fast pricing and online sync
This commit is contained in:
@@ -63,6 +63,14 @@ describe('buildModelsDevTieredPricing', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('fails closed when a legacy long-context copy has no authoritative tier boundary', () => {
|
||||
expect(buildModelsDevTieredPricing({
|
||||
input: 5,
|
||||
output: 30,
|
||||
context_over_200k: { input: 10, output: 45 },
|
||||
})).toBeNull()
|
||||
})
|
||||
|
||||
it('allows special token dimensions only when they use the base token price', () => {
|
||||
expect(buildModelsDevTieredPricing({
|
||||
input: 1,
|
||||
@@ -214,7 +222,7 @@ describe('resolveModelsDevTieredPricing', () => {
|
||||
expect(resolveModelsDevTieredPricing('openai', 'gpt-5.6-sol', undefined)).toBeNull()
|
||||
})
|
||||
|
||||
it('keeps a models.dev fast cost as an explicit Priority catalog when bands differ', () => {
|
||||
it('collapses a flat models.dev Fast cost to the Standard first band multiplier', () => {
|
||||
expect(resolveModelsDevTieredPricing('openai', 'gpt-5.6-sol', {
|
||||
input: 5,
|
||||
output: 30,
|
||||
@@ -235,12 +243,81 @@ describe('resolveModelsDevTieredPricing', () => {
|
||||
],
|
||||
processing_tiers: {
|
||||
priority: {
|
||||
tiers: [{ up_to: null, input_price_per_1m: 10, output_price_per_1m: 60 }],
|
||||
price_multiplier: 2,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('maps the GPT-5.6 Fast cost and ignores the legacy context copy', () => {
|
||||
expect(resolveModelsDevTieredPricing('openai', 'gpt-5.6-sol', {
|
||||
input: 5,
|
||||
output: 30,
|
||||
cache_read: 0.5,
|
||||
cache_write: 6.25,
|
||||
tiers: [{
|
||||
input: 10,
|
||||
output: 45,
|
||||
cache_read: 1,
|
||||
cache_write: 12.5,
|
||||
tier: { type: 'context', size: 272_000 },
|
||||
}],
|
||||
context_over_200k: {
|
||||
input: 10,
|
||||
output: 45,
|
||||
cache_read: 1,
|
||||
cache_write: 12.5,
|
||||
},
|
||||
}, {
|
||||
fast: {
|
||||
cost: {
|
||||
input: 10,
|
||||
output: 60,
|
||||
cache_read: 1,
|
||||
cache_write: 12.5,
|
||||
},
|
||||
provider: { body: { service_tier: 'priority' } },
|
||||
},
|
||||
})).toEqual({
|
||||
tiers: [
|
||||
{
|
||||
up_to: 271_999,
|
||||
input_price_per_1m: 5,
|
||||
output_price_per_1m: 30,
|
||||
cache_creation_price_per_1m: 6.25,
|
||||
cache_read_price_per_1m: 0.5,
|
||||
},
|
||||
{
|
||||
up_to: null,
|
||||
input_price_per_1m: 10,
|
||||
output_price_per_1m: 45,
|
||||
cache_creation_price_per_1m: 12.5,
|
||||
cache_read_price_per_1m: 1,
|
||||
},
|
||||
],
|
||||
processing_tiers: {
|
||||
priority: { price_multiplier: 2 },
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('fails closed when an experimental mode tries to supply context tiers', () => {
|
||||
expect(resolveModelsDevTieredPricing('openai', 'gpt-5.6-sol', {
|
||||
input: 5,
|
||||
output: 30,
|
||||
tiers: [{ input: 10, output: 45, tier: { type: 'context', size: 272_000 } }],
|
||||
}, {
|
||||
fast: {
|
||||
cost: {
|
||||
input: 10,
|
||||
output: 60,
|
||||
tiers: [{ input: 20, output: 90, tier: { type: 'context', size: 272_000 } }],
|
||||
},
|
||||
provider: { body: { service_tier: 'priority' } },
|
||||
},
|
||||
})?.processing_tiers).toBeUndefined()
|
||||
})
|
||||
|
||||
it('uses a multiplier only when every fast price has the same ratio', () => {
|
||||
expect(resolveModelsDevTieredPricing('anthropic', 'claude-opus-4.8', {
|
||||
input: 5,
|
||||
@@ -269,6 +346,27 @@ describe('resolveModelsDevTieredPricing', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps a non-uniform Fast cost as one explicit unbounded band', () => {
|
||||
expect(resolveModelsDevTieredPricing('openai', 'future-model', {
|
||||
input: 5,
|
||||
output: 30,
|
||||
tiers: [{
|
||||
input: 10,
|
||||
output: 45,
|
||||
tier: { type: 'context', size: 272_000 },
|
||||
}],
|
||||
}, {
|
||||
fast: {
|
||||
cost: { input: 10, output: 75 },
|
||||
provider: { body: { service_tier: 'priority' } },
|
||||
},
|
||||
})?.processing_tiers).toEqual({
|
||||
priority: {
|
||||
tiers: [{ up_to: null, input_price_per_1m: 10, output_price_per_1m: 75 }],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('uses the standard catalog when an imported tier has a zero default ratio', () => {
|
||||
expect(resolveModelsDevTieredPricing('openai', 'gpt-5.6-sol', {
|
||||
input: 5,
|
||||
|
||||
@@ -2,18 +2,21 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const apiMocks = vi.hoisted(() => ({
|
||||
get: vi.fn(),
|
||||
delete: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/api/client', () => ({
|
||||
default: { get: apiMocks.get },
|
||||
default: { get: apiMocks.get, delete: apiMocks.delete },
|
||||
}))
|
||||
|
||||
import { clearModelsDevCache, getModelsDevList } from '@/api/models-dev'
|
||||
import { clearModelsDevCache, getModelsDevList, refreshModelsDevList } from '@/api/models-dev'
|
||||
|
||||
beforeEach(() => {
|
||||
clearModelsDevCache()
|
||||
localStorage.clear()
|
||||
apiMocks.get.mockReset()
|
||||
apiMocks.delete.mockReset()
|
||||
apiMocks.delete.mockResolvedValue({ data: { cleared: true } })
|
||||
})
|
||||
|
||||
describe('getModelsDevList', () => {
|
||||
@@ -34,7 +37,15 @@ describe('getModelsDevList', () => {
|
||||
input: ['text', 'image'],
|
||||
output: ['text', 'image'],
|
||||
},
|
||||
cost: { input: 2, output: 4 },
|
||||
cost: {
|
||||
input: 2,
|
||||
output: 4,
|
||||
tiers: [{
|
||||
input: 4,
|
||||
output: 8,
|
||||
tier: { type: 'context', size: 100_000 },
|
||||
}],
|
||||
},
|
||||
experimental: {
|
||||
modes: {
|
||||
fast: {
|
||||
@@ -86,4 +97,29 @@ describe('getModelsDevList', () => {
|
||||
})
|
||||
expect(audioPriced?.tieredPricing).toBeUndefined()
|
||||
})
|
||||
|
||||
it('clears the gateway cache before rebuilding the online model list', async () => {
|
||||
apiMocks.get.mockResolvedValue({
|
||||
data: {
|
||||
openai: {
|
||||
name: 'OpenAI',
|
||||
official: true,
|
||||
models: {
|
||||
'gpt-test': {
|
||||
id: 'gpt-test',
|
||||
name: 'GPT Test',
|
||||
cost: { input: 2, output: 4 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
await getModelsDevList(false)
|
||||
await refreshModelsDevList(false)
|
||||
|
||||
expect(apiMocks.delete).toHaveBeenCalledOnce()
|
||||
expect(apiMocks.delete).toHaveBeenCalledWith('/api/admin/models/external/cache')
|
||||
expect(apiMocks.get).toHaveBeenCalledTimes(2)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user