fix: scope deepseek budget and align supported model aliases

This commit is contained in:
Guilhem Lemouel
2026-09-22 09:06:55 +02:00
parent fa4e6ce832
commit acf1c1c5b2
4 changed files with 28 additions and 14 deletions
@@ -124,21 +124,29 @@ afterEach(() => {
})
describe('DeepSeek output budget', () => {
it.each(['deepseek-flash', 'deepseek-v4-flash', 'deepseek-v4-pro'])(
'sends the full reasoning and answer budget for %s',
async (model) => {
const { getCompletion, getNonStreamingMetadataCompletion, METADATA_MAX_TOKENS } =
await import('./lib')
h.currentModel = { provider: 'deepseek', model }
it.each([
'deepseek-flash',
'deepseek-v4-flash',
'deepseek-v4-pro',
'deepseek-chat',
'deepseek-reasoner'
])('sends the full reasoning and answer budget for %s', async (model) => {
const { getCompletion } = await import('./lib')
h.currentModel = { provider: 'deepseek', model }
await getCompletion(messages, new AbortController())
expect(openaiCreate.mock.calls[0][0].max_tokens).toBe(393216)
await getCompletion(messages, new AbortController())
expect(openaiCreate.mock.calls[0][0].max_tokens).toBe(393216)
})
openaiCreate.mockClear()
await getNonStreamingMetadataCompletion(messages, new AbortController())
expect(openaiCreate.mock.calls[0][0].max_tokens).toBe(METADATA_MAX_TOKENS)
}
)
it('preserves the metadata cap and third-party provider defaults', async () => {
const { getNonStreamingMetadataCompletion, getModelMaxTokens, METADATA_MAX_TOKENS } =
await import('./lib')
h.currentModel = { provider: 'deepseek', model: 'deepseek-flash' }
await getNonStreamingMetadataCompletion(messages, new AbortController())
expect(openaiCreate.mock.calls[0][0].max_tokens).toBe(METADATA_MAX_TOKENS)
expect(getModelMaxTokens('customai', 'deepseek-flash')).toBe(8192)
expect(getModelMaxTokens('azure_foundry', 'deepseek-v4-pro')).toBe(8192)
})
})
describe('Anthropic Messages API routing', () => {
@@ -263,6 +263,7 @@ describe('model context windows', () => {
expect(getKnownModelContextWindow('gemini-3-flash')).toBe(1000000)
expect(getKnownModelContextWindow('gemini-2.5-flash')).toBe(1000000)
expect(getKnownModelContextWindow('deepseek-v4-pro')).toBe(1000000)
expect(getKnownModelContextWindow('deepseek-flash')).toBe(1000000)
expect(getKnownModelContextWindow('deepseek-chat')).toBe(1000000)
expect(getKnownModelContextWindow('deepseek-reasoner')).toBe(1000000)
})
+5 -1
View File
@@ -15,6 +15,7 @@ import { get, type Writable } from 'svelte/store'
import { OpenAPI, ResourceService, type Script } from '../../gen'
import { EDIT_CONFIG, FIX_CONFIG, GEN_CONFIG } from './prompts'
import {
parseModelId,
requiresMaxCompletionTokens,
usesAnthropicMessagesApi,
usesOpenRouterPromptCaching
@@ -310,7 +311,10 @@ export async function fetchAvailableModels(
}
export function getModelMaxTokens(provider: AIProvider, model: string) {
if (/^(deepseek-flash|deepseek-v4-(flash|pro))$/.test(model.split('/').pop() ?? '')) {
if (
provider === 'deepseek' &&
/^(deepseek-(flash|chat|reasoner)|deepseek-v4-(flash|pro))$/.test(parseModelId(model).base)
) {
// DeepSeek counts reasoning against the output budget as well as the answer.
return 393216
} else if (model.includes('gpt-5')) {
@@ -100,6 +100,7 @@ const MODEL_CONTEXT_WINDOWS: [name: string, contextWindow: number][] = [
// deepseek-reasoner aliases were retired 2026-07-24 but can still sit in a
// saved selection, so they keep resolving to the window they had.
['deepseek-v4', 1_000_000],
['deepseek-flash', 1_000_000],
['deepseek-chat', 1_000_000],
['deepseek-reasoner', 1_000_000],
['deepseek', 128_000],