Fix custom provider context resolution (#468)
Co-authored-by: ekko <152005280+EKKOLearnAI@users.noreply.github.com>
This commit is contained in:
@@ -158,4 +158,169 @@ describe('getModelContextLength', () => {
|
||||
|
||||
expect(getModelContextLength()).toBe(1_000_000)
|
||||
})
|
||||
|
||||
it('resolves provider: custom through model.base_url before falling back to the default context length', async () => {
|
||||
writeConfig(`model:\n default: deepseek-v4-pro\n provider: custom\n base_url: https://api.deepseek.com\n`)
|
||||
writeModelsCache({
|
||||
deepseek: {
|
||||
models: {
|
||||
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(1_000_000)
|
||||
})
|
||||
|
||||
it('resolves custom:name providers when the matched custom provider base_url points at a builtin provider', async () => {
|
||||
writeConfig(`model:\n default: deepseek-v4-pro\n provider: custom:deepseek\n\ncustom_providers:\n - name: deepseek\n base_url: https://api.deepseek.com\n model: deepseek-v4-pro\n`)
|
||||
writeModelsCache({
|
||||
deepseek: {
|
||||
models: {
|
||||
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(1_000_000)
|
||||
})
|
||||
|
||||
it('prefers the builtin provider inferred from a matched custom provider base_url over an arbitrary custom provider name', async () => {
|
||||
writeConfig(`model:\n default: shared-model\n provider: custom:corp-proxy\n\ncustom_providers:\n - name: corp-proxy\n base_url: https://api.deepseek.com\n model: shared-model\n`)
|
||||
writeModelsCache({
|
||||
deepseek: {
|
||||
models: {
|
||||
'shared-model': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
openai: {
|
||||
models: {
|
||||
'shared-model': { limit: { context: 400_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(1_000_000)
|
||||
})
|
||||
|
||||
it('does not trust a stale custom:name provider hint without a matching custom provider entry', async () => {
|
||||
writeConfig(`model:\n default: deepseek-v4-pro\n provider: custom:deepseek\n`)
|
||||
writeModelsCache({
|
||||
deepseek: {
|
||||
models: {
|
||||
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(200_000)
|
||||
})
|
||||
|
||||
it('does not trust custom:name alone when the matched custom provider entry points at an unknown proxy url', async () => {
|
||||
writeConfig(`model:\n default: deepseek-v4-pro\n provider: custom:deepseek\n\ncustom_providers:\n - name: deepseek\n base_url: https://proxy.example.com/v1\n model: deepseek-v4-pro\n`)
|
||||
writeModelsCache({
|
||||
deepseek: {
|
||||
models: {
|
||||
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(200_000)
|
||||
})
|
||||
|
||||
it('does not fall through to a unique global match after a resolved custom:name provider misses in its scoped cache provider', async () => {
|
||||
writeConfig(`model:\n default: gpt-5.5\n provider: custom:deepseek\n\ncustom_providers:\n - name: deepseek\n base_url: https://api.deepseek.com\n model: gpt-5.5\n`)
|
||||
writeModelsCache({
|
||||
openai: {
|
||||
models: {
|
||||
'gpt-5.5': { limit: { context: 400_000 } },
|
||||
},
|
||||
},
|
||||
deepseek: {
|
||||
models: {
|
||||
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(200_000)
|
||||
})
|
||||
|
||||
it('allows a unique global model-name fallback for unresolved custom providers', async () => {
|
||||
writeConfig(`model:\n default: deepseek-v4-pro\n provider: custom\n base_url: https://proxy.example.com/v1\n`)
|
||||
writeModelsCache({
|
||||
deepseek: {
|
||||
models: {
|
||||
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(1_000_000)
|
||||
})
|
||||
|
||||
it('still allows the unique global fallback when provider: custom matches a custom provider entry that cannot be mapped to a builtin cache provider', async () => {
|
||||
writeConfig(`model:\n default: deepseek-v4-pro\n provider: custom\n\ncustom_providers:\n - name: corp-proxy\n base_url: https://proxy.example.com/v1\n model: deepseek-v4-pro\n`)
|
||||
writeModelsCache({
|
||||
deepseek: {
|
||||
models: {
|
||||
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(1_000_000)
|
||||
})
|
||||
|
||||
it('keeps the unresolved custom-provider fallback strict to exact or case-insensitive model-name matches', async () => {
|
||||
writeConfig(`model:\n default: gpt-5\n provider: custom\n base_url: https://proxy.example.com/v1\n`)
|
||||
writeModelsCache({
|
||||
vercel: {
|
||||
models: {
|
||||
'openai/gpt-5': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(200_000)
|
||||
})
|
||||
|
||||
it('does not guess across multiple cache providers when a custom provider remains unresolved', async () => {
|
||||
writeConfig(`model:\n default: shared-model\n provider: custom\n base_url: https://proxy.example.com/v1\n`)
|
||||
writeModelsCache({
|
||||
deepseek: {
|
||||
models: {
|
||||
'shared-model': { limit: { context: 1_000_000 } },
|
||||
},
|
||||
},
|
||||
openai: {
|
||||
models: {
|
||||
'shared-model': { limit: { context: 400_000 } },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { getModelContextLength } = await loadModelContext()
|
||||
|
||||
expect(getModelContextLength()).toBe(200_000)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user