fix: use 1m fallback for unknown model context
Build / build (push) Canceled after 0s
Playwright / e2e (push) Canceled after 0s

This commit is contained in:
2026-11-05 12:15:17 +08:00
parent c50a6f63d9
commit e35a5626c6
5 changed files with 29 additions and 15 deletions
@@ -0,0 +1,9 @@
---
date: 2026-11-05
pr: pending
feature: Unknown model context fallback
impact: When no model context length can be resolved, the Web UI estimates it as 1000000 tokens instead of 256000. Explicit settings and model metadata retain priority.
---
This estimate also affects Web UI compression thresholds for models with no
known context length. It does not change the model provider's actual limit.
+1 -1
View File
@@ -1415,7 +1415,7 @@ export default {
customType: 'Custom',
provider: 'Provider',
contextLength: 'Context Length',
contextLengthPlaceholder: 'e.g. 256000 (optional)',
contextLengthPlaceholder: 'Optional; estimated as 1000000 when unknown',
apiMode: 'API Mode',
local: 'Local ({host})',
selectProviderRequired: 'Please select a provider',
+1 -1
View File
@@ -1415,7 +1415,7 @@ export default {
customType: '自定义',
provider: 'Provider',
contextLength: '上下文长度',
contextLengthPlaceholder: '例如 256000(可选)',
contextLengthPlaceholder: '可选;未知时按 1000000 估算',
apiMode: 'API 模式',
local: '本地 ({host})',
selectProviderRequired: '请选择 Provider',
@@ -9,7 +9,7 @@ import { getCompatibleCustomProviders } from './custom-providers-compat'
const HERMES_BASE = detectHermesHome()
const MODELS_DEV_CACHE = resolve(HERMES_BASE, 'models_dev_cache.json')
const DEFAULT_CONTEXT_LENGTH = 256_000
const DEFAULT_CONTEXT_LENGTH = 1_000_000
export interface ModelContextLengthOptions {
profile?: string
+17 -12
View File
@@ -59,6 +59,11 @@ describe('getModelContextLength', () => {
homeDir = ''
})
it('uses one million tokens when no model context is available', async () => {
const { getModelContextLength } = await loadModelContext()
expect(getModelContextLength()).toBe(1_000_000)
})
it('does not borrow a same-named model context from another provider when the configured provider is uncached', async () => {
writeConfig(`model:\n default: gpt-5.5\n provider: openai-codex\n`)
writeModelsCache({
@@ -71,7 +76,7 @@ describe('getModelContextLength', () => {
const { getModelContextLength } = await loadModelContext()
expect(getModelContextLength()).toBe(256_000)
expect(getModelContextLength()).toBe(1_000_000)
})
it('does not scan other providers when the configured provider exists without that model', async () => {
@@ -91,7 +96,7 @@ describe('getModelContextLength', () => {
const { getModelContextLength } = await loadModelContext()
expect(getModelContextLength()).toBe(256_000)
expect(getModelContextLength()).toBe(1_000_000)
})
it('uses the configured provider cache entry when the provider matches', async () => {
@@ -250,14 +255,14 @@ describe('getModelContextLength', () => {
writeModelsCache({
deepseek: {
models: {
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
'deepseek-v4-pro': { limit: { context: 1_050_000 } },
},
},
})
const { getModelContextLength } = await loadModelContext()
expect(getModelContextLength()).toBe(256_000)
expect(getModelContextLength()).toBe(1_000_000)
})
it('does not trust custom:name alone when the matched custom provider entry points at an unknown proxy url', async () => {
@@ -265,14 +270,14 @@ describe('getModelContextLength', () => {
writeModelsCache({
deepseek: {
models: {
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
'deepseek-v4-pro': { limit: { context: 1_050_000 } },
},
},
})
const { getModelContextLength } = await loadModelContext()
expect(getModelContextLength()).toBe(256_000)
expect(getModelContextLength()).toBe(1_000_000)
})
it('does not fall through to a unique global match after a resolved custom:name provider misses in its scoped cache provider', async () => {
@@ -285,14 +290,14 @@ describe('getModelContextLength', () => {
},
deepseek: {
models: {
'deepseek-v4-pro': { limit: { context: 1_000_000 } },
'deepseek-v4-pro': { limit: { context: 1_050_000 } },
},
},
})
const { getModelContextLength } = await loadModelContext()
expect(getModelContextLength()).toBe(256_000)
expect(getModelContextLength()).toBe(1_000_000)
})
it('allows a unique global model-name fallback for unresolved custom providers', async () => {
@@ -330,14 +335,14 @@ describe('getModelContextLength', () => {
writeModelsCache({
vercel: {
models: {
'openai/gpt-5': { limit: { context: 1_000_000 } },
'openai/gpt-5': { limit: { context: 1_050_000 } },
},
},
})
const { getModelContextLength } = await loadModelContext()
expect(getModelContextLength()).toBe(256_000)
expect(getModelContextLength()).toBe(1_000_000)
})
it('does not guess across multiple cache providers when a custom provider remains unresolved', async () => {
@@ -345,7 +350,7 @@ describe('getModelContextLength', () => {
writeModelsCache({
deepseek: {
models: {
'shared-model': { limit: { context: 1_000_000 } },
'shared-model': { limit: { context: 1_050_000 } },
},
},
openai: {
@@ -357,6 +362,6 @@ describe('getModelContextLength', () => {
const { getModelContextLength } = await loadModelContext()
expect(getModelContextLength()).toBe(256_000)
expect(getModelContextLength()).toBe(1_000_000)
})
})