fix(runtime): update domestic provider model presets

Tested:
- bun test src/server/__tests__/provider-presets.test.ts src/server/__tests__/provider-runtime-env.test.ts src/utils/model/modelContextWindows.test.ts src/utils/__tests__/thinking.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/settings.test.ts
- bun run check:server
- git diff --check

Not-tested:
- bun run verify
- coverage gates

Confidence: high
Scope-risk: moderate
This commit is contained in:
程序员阿江(Relakkes) 2026-06-27 16:51:43 +08:00
parent 08c2d8cf5b
commit 84c5685b1a
6 changed files with 188 additions and 51 deletions

View File

@ -79,25 +79,29 @@ describe('provider presets API', () => {
expect(ollama?.authStrategy).toBe('auth_token_empty_api_key')
expect(ollama?.defaultModels.main).toBe('qwen3.6:27b')
expect(deepseek?.authStrategy).toBe('auth_token')
expect(deepseek?.defaultModels.main).toBe('deepseek-v4-pro')
expect(deepseek?.defaultModels.main).toBe('deepseek-v4-pro[1m]')
expect(deepseek?.defaultModels.haiku).toBe('deepseek-v4-flash')
expect(deepseek?.defaultModels.sonnet).toBe('deepseek-v4-pro')
expect(deepseek?.defaultModels.opus).toBe('deepseek-v4-pro')
expect(deepseek?.defaultModels.sonnet).toBe('deepseek-v4-pro[1m]')
expect(deepseek?.defaultModels.opus).toBe('deepseek-v4-pro[1m]')
expect(deepseek?.defaultEnv?.CC_HAHA_SEND_DISABLED_THINKING).toBeUndefined()
expect(deepseek?.defaultEnv?.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES).toBe(
'thinking,effort,adaptive_thinking,max_effort',
)
expect(zhipu?.authStrategy).toBe('auth_token')
expect(zhipu?.defaultModels.main).toBe('glm-5.1')
expect(zhipu?.defaultModels.haiku).toBe('glm-4.5-air')
expect(zhipu?.defaultModels.sonnet).toBe('glm-5-turbo')
expect(zhipu?.defaultModels.opus).toBe('glm-5.1')
expect(kimi?.baseUrl).toBe('https://api.kimi.com/coding')
expect(zhipu?.defaultModels.main).toBe('glm-5.2[1m]')
expect(zhipu?.defaultModels.haiku).toBe('glm-4.7')
expect(zhipu?.defaultModels.sonnet).toBe('glm-5.2[1m]')
expect(zhipu?.defaultModels.opus).toBe('glm-5.2[1m]')
expect(zhipu?.defaultEnv?.CLAUDE_CODE_AUTO_COMPACT_WINDOW).toBe('1000000')
expect(kimi?.baseUrl).toBe('https://api.moonshot.cn/anthropic')
expect(kimi?.authStrategy).toBe('auth_token')
expect(kimi?.defaultModels.main).toBe('kimi-k2.6')
expect(kimi?.defaultEnv?.CC_HAHA_SEND_DISABLED_THINKING).toBe('1')
expect(kimi?.defaultModels.main).toBe('kimi-k2.7-code')
expect(kimi?.defaultEnv?.CC_HAHA_SEND_DISABLED_THINKING).toBeUndefined()
expect(kimi?.defaultEnv?.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES).toBe('thinking')
expect(minimax?.authStrategy).toBe('auth_token')
expect(minimax?.defaultModels.main).toBe('MiniMax-M3')
expect(minimax?.defaultModels.main).toBe('MiniMax-M3[1m]')
expect(minimax?.defaultEnv?.CLAUDE_CODE_AUTO_COMPACT_WINDOW).toBe('1000000')
expect(minimax?.defaultEnv?.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES).toBe('thinking,adaptive_thinking')
expect(minimax?.modelContextWindows?.['MiniMax-M3']).toBe(1000000)
expect(jiekouai?.baseUrl).toBe('https://api.jiekou.ai/anthropic')
expect(jiekouai?.authStrategy).toBe('auth_token')
@ -140,11 +144,14 @@ describe('provider presets API', () => {
expect(deepseek?.modelContextWindows?.['deepseek-v4-flash']).toBe(1000000)
expect(zhipu?.apiKeyUrl).toBe('https://www.bigmodel.cn/invite?icode=d41B2qi8Z5xNwTGLNPPF3OZLO2QH3C0EBTSr%2BArzMw4%3D')
expect(zhipu?.promoText).toContain('cc-haha')
expect(zhipu?.defaultEnv?.CC_HAHA_SEND_DISABLED_THINKING).toBe('1')
expect(zhipu?.modelContextWindows?.['glm-5.2']).toBe(200000)
expect(zhipu?.defaultEnv?.CC_HAHA_SEND_DISABLED_THINKING).toBeUndefined()
expect(zhipu?.modelContextWindows?.['glm-5.2']).toBe(1000000)
expect(zhipu?.modelContextWindows?.['glm-5.1']).toBe(200000)
expect(zhipu?.modelContextWindows?.['glm-4.7']).toBe(200000)
expect(zhipu?.modelContextWindows?.['glm-4.5-air']).toBe(128000)
expect(kimi?.apiKeyUrl).toBe('https://platform.kimi.com/console/api-keys')
expect(kimi?.modelContextWindows?.['kimi-k2.7-code']).toBe(262144)
expect(kimi?.modelContextWindows?.['kimi-k2.7-code-highspeed']).toBe(262144)
expect(kimi?.modelContextWindows?.['kimi-k2.6']).toBe(262144)
expect(minimax?.apiKeyUrl).toBe('https://platform.minimaxi.com/subscribe/token-plan?code=1TG2Cseab2&source=link')
expect(jiekouai?.apiKeyUrl).toBe('https://jiekou.ai/referral?invited_code=OBNU3K')

View File

@ -189,4 +189,72 @@ describe('providerRuntimeEnv', () => {
expect(env.ENABLE_TOOL_SEARCH).toBeUndefined()
})
test('applies updated docs-backed preset env for domestic Anthropic-compatible providers', async () => {
await writeJson(path.join(tmpDir, 'cc-haha', 'providers.json'), {
activeId: 'provider-kimi',
providers: [
{
id: 'provider-kimi',
presetId: 'kimi',
name: 'Kimi',
apiKey: 'sk-kimi',
authStrategy: 'auth_token',
baseUrl: 'https://api.moonshot.cn/anthropic',
apiFormat: 'anthropic',
models: {
main: 'kimi-k2.7-code',
haiku: 'kimi-k2.7-code',
sonnet: 'kimi-k2.7-code',
opus: 'kimi-k2.7-code',
},
},
],
})
const kimiEnv = readActiveProviderManagedEnv(tmpDir)
expect(kimiEnv).toMatchObject({
ANTHROPIC_BASE_URL: 'https://api.moonshot.cn/anthropic',
ANTHROPIC_MODEL: 'kimi-k2.7-code',
ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES: 'thinking',
})
expect(JSON.parse(kimiEnv!.CLAUDE_CODE_MODEL_CONTEXT_WINDOWS)).toMatchObject({
'kimi-k2.7-code': 262144,
'kimi-k2.7-code-highspeed': 262144,
})
await writeJson(path.join(tmpDir, 'cc-haha', 'providers.json'), {
activeId: 'provider-zhipu',
providers: [
{
id: 'provider-zhipu',
presetId: 'zhipuglm',
name: 'Zhipu GLM',
apiKey: 'sk-zhipu',
authStrategy: 'auth_token',
baseUrl: 'https://open.bigmodel.cn/api/anthropic',
apiFormat: 'anthropic',
models: {
main: 'glm-5.2[1m]',
haiku: 'glm-4.7',
sonnet: 'glm-5.2[1m]',
opus: 'glm-5.2[1m]',
},
},
],
})
const zhipuEnv = readActiveProviderManagedEnv(tmpDir)
expect(zhipuEnv).toMatchObject({
ANTHROPIC_MODEL: 'glm-5.2[1m]',
ANTHROPIC_DEFAULT_HAIKU_MODEL: 'glm-4.7',
CLAUDE_CODE_AUTO_COMPACT_WINDOW: '1000000',
})
expect(JSON.parse(zhipuEnv!.CLAUDE_CODE_MODEL_CONTEXT_WINDOWS)).toMatchObject({
'glm-5.2[1m]': 1000000,
'glm-4.7': 200000,
})
})
})

View File

@ -19,21 +19,23 @@
"baseUrl": "https://api.deepseek.com/anthropic",
"apiFormat": "anthropic",
"defaultModels": {
"main": "deepseek-v4-pro",
"main": "deepseek-v4-pro[1m]",
"haiku": "deepseek-v4-flash",
"sonnet": "deepseek-v4-pro",
"opus": "deepseek-v4-pro"
"sonnet": "deepseek-v4-pro[1m]",
"opus": "deepseek-v4-pro[1m]"
},
"needsApiKey": true,
"websiteUrl": "https://platform.deepseek.com",
"apiKeyUrl": "https://platform.deepseek.com/api_keys",
"authStrategy": "auth_token",
"defaultEnv": {
"CLAUDE_CODE_AUTO_COMPACT_WINDOW": "1000000",
"ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES": "thinking,effort,adaptive_thinking,max_effort",
"ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES": "thinking,effort,adaptive_thinking,max_effort",
"ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES": "thinking,effort,adaptive_thinking,max_effort"
},
"modelContextWindows": {
"deepseek-v4-pro[1m]": 1000000,
"deepseek-v4-pro": 1000000,
"deepseek-v4-flash": 1000000,
"deepseek-chat": 1000000,
@ -46,10 +48,10 @@
"baseUrl": "https://open.bigmodel.cn/api/anthropic",
"apiFormat": "anthropic",
"defaultModels": {
"main": "glm-5.1",
"haiku": "glm-4.5-air",
"sonnet": "glm-5-turbo",
"opus": "glm-5.1"
"main": "glm-5.2[1m]",
"haiku": "glm-4.7",
"sonnet": "glm-5.2[1m]",
"opus": "glm-5.2[1m]"
},
"needsApiKey": true,
"websiteUrl": "https://open.bigmodel.cn",
@ -57,40 +59,42 @@
"promoText": "智谱 GLM 为 cc-haha 用户准备了专属邀请福利,使用此链接注册后可领取新用户权益。",
"authStrategy": "auth_token",
"defaultEnv": {
"CC_HAHA_SEND_DISABLED_THINKING": "1"
"CLAUDE_CODE_AUTO_COMPACT_WINDOW": "1000000"
},
"modelContextWindows": {
"glm-5.2": 200000,
"glm-5.2[1m]": 1000000,
"glm-5.2": 1000000,
"glm-5.1": 200000,
"glm-5-turbo": 200000,
"glm-4.7": 200000,
"glm-4.5-air": 128000
}
},
{
"id": "kimi",
"name": "Kimi",
"baseUrl": "https://api.kimi.com/coding",
"baseUrl": "https://api.moonshot.cn/anthropic",
"apiFormat": "anthropic",
"defaultModels": {
"main": "kimi-k2.6",
"haiku": "kimi-k2.6",
"sonnet": "kimi-k2.6",
"opus": "kimi-k2.6"
"main": "kimi-k2.7-code",
"haiku": "kimi-k2.7-code",
"sonnet": "kimi-k2.7-code",
"opus": "kimi-k2.7-code"
},
"needsApiKey": true,
"websiteUrl": "https://platform.moonshot.cn",
"websiteUrl": "https://platform.kimi.com",
"apiKeyUrl": "https://platform.kimi.com/console/api-keys",
"authStrategy": "auth_token",
"defaultEnv": {
"CC_HAHA_SEND_DISABLED_THINKING": "1"
"ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES": "thinking",
"ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES": "thinking",
"ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES": "thinking"
},
"modelContextWindows": {
"kimi-k2.7-code": 262144,
"kimi-k2.7-code-highspeed": 262144,
"kimi-k2.6": 262144,
"kimi-k2.5": 262144,
"kimi-k2-0905-preview": 262144,
"kimi-k2-turbo-preview": 262144,
"kimi-k2-thinking": 262144,
"kimi-k2-thinking-turbo": 262144
"kimi-k2.5": 262144
}
},
{
@ -99,16 +103,23 @@
"baseUrl": "https://api.minimaxi.com/anthropic",
"apiFormat": "anthropic",
"defaultModels": {
"main": "MiniMax-M3",
"haiku": "MiniMax-M3",
"sonnet": "MiniMax-M3",
"opus": "MiniMax-M3"
"main": "MiniMax-M3[1m]",
"haiku": "MiniMax-M3[1m]",
"sonnet": "MiniMax-M3[1m]",
"opus": "MiniMax-M3[1m]"
},
"needsApiKey": true,
"websiteUrl": "https://platform.minimaxi.com",
"apiKeyUrl": "https://platform.minimaxi.com/subscribe/token-plan?code=1TG2Cseab2&source=link",
"authStrategy": "auth_token",
"defaultEnv": {
"CLAUDE_CODE_AUTO_COMPACT_WINDOW": "1000000",
"ANTHROPIC_DEFAULT_HAIKU_MODEL_SUPPORTED_CAPABILITIES": "thinking,adaptive_thinking",
"ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES": "thinking,adaptive_thinking",
"ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES": "thinking,adaptive_thinking"
},
"modelContextWindows": {
"MiniMax-M3[1m]": 1000000,
"MiniMax-M3": 1000000,
"MiniMax-M2.7": 204800,
"MiniMax-M2.7-highspeed": 204800

View File

@ -93,16 +93,29 @@ describe('provider-aware thinking support', () => {
expect(shouldSendExplicitDisabledThinking()).toBe(false)
})
test('MiniMax preset models declare thinking support without effort passthrough', () => {
test('MiniMax preset models declare adaptive thinking without effort passthrough', () => {
process.env.ANTHROPIC_BASE_URL = 'https://api.minimaxi.com/anthropic'
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL = 'MiniMax-M3'
delete process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL = 'MiniMax-M3[1m]'
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES =
'thinking,adaptive_thinking'
clearCapabilityCache()
expect(modelSupportsThinking('MiniMax-M3')).toBe(true)
expect(modelSupportsAdaptiveThinking('MiniMax-M3')).toBe(false)
expect(modelSupportsEffort('MiniMax-M3')).toBe(false)
expect(modelSupportsMaxEffort('MiniMax-M3')).toBe(false)
expect(modelSupportsThinking('MiniMax-M3[1m]')).toBe(true)
expect(modelSupportsAdaptiveThinking('MiniMax-M3[1m]')).toBe(true)
expect(modelSupportsEffort('MiniMax-M3[1m]')).toBe(false)
expect(modelSupportsMaxEffort('MiniMax-M3[1m]')).toBe(false)
})
test('Kimi preset models declare thinking without effort passthrough', () => {
process.env.ANTHROPIC_BASE_URL = 'https://api.moonshot.cn/anthropic'
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL = 'kimi-k2.7-code'
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_SUPPORTED_CAPABILITIES = 'thinking'
clearCapabilityCache()
expect(modelSupportsThinking('kimi-k2.7-code')).toBe(true)
expect(modelSupportsAdaptiveThinking('kimi-k2.7-code')).toBe(false)
expect(modelSupportsEffort('kimi-k2.7-code')).toBe(false)
expect(modelSupportsMaxEffort('kimi-k2.7-code')).toBe(false)
})
test('third-party base URLs do not default unknown model names to effort support', () => {

View File

@ -0,0 +1,31 @@
import { describe, expect, test } from 'bun:test'
import {
getConfiguredOrBuiltInModelContextWindow,
getModelContextWindowFromEnvValue,
} from './modelContextWindows.js'
describe('model context windows', () => {
test('recognizes updated domestic coding model context windows', () => {
expect(getConfiguredOrBuiltInModelContextWindow('kimi-k2.7-code')).toBe(262_144)
expect(getConfiguredOrBuiltInModelContextWindow('kimi-k2.7-code-highspeed')).toBe(262_144)
expect(getConfiguredOrBuiltInModelContextWindow('glm-5.2')).toBe(1_000_000)
expect(getConfiguredOrBuiltInModelContextWindow('glm-4.7')).toBe(200_000)
expect(getConfiguredOrBuiltInModelContextWindow('qwen/qwen3.6-27b')).toBe(262_144)
expect(getConfiguredOrBuiltInModelContextWindow('qwen3.6:27b')).toBe(262_144)
expect(getConfiguredOrBuiltInModelContextWindow('qwen3.7-plus-2026-02-15')).toBe(1_000_000)
expect(getConfiguredOrBuiltInModelContextWindow('qwen3-coder-plus')).toBe(1_000_000)
expect(getConfiguredOrBuiltInModelContextWindow('qwen3-coder-next')).toBe(262_144)
})
test('matches configured base model windows for Claude Code 1m aliases', () => {
expect(getModelContextWindowFromEnvValue(
'MiniMax-M3[1m]',
JSON.stringify({ 'MiniMax-M3': 1_000_000 }),
)).toBe(1_000_000)
expect(getModelContextWindowFromEnvValue(
'glm-5.2[1m]',
JSON.stringify({ 'glm-5.2': 1_000_000 }),
)).toBe(1_000_000)
})
})

View File

@ -10,6 +10,8 @@ const DIRECT_MODEL_CONTEXT_WINDOWS: Record<string, number> = {
'deepseek-v4-flash': 1_000_000,
'deepseek-chat': 1_000_000,
'deepseek-reasoner': 1_000_000,
'kimi-k2.7-code': 262_144,
'kimi-k2.7-code-highspeed': 262_144,
'kimi-k2.6': 262_144,
'kimi-k2.5': 262_144,
'kimi-k2-0905-preview': 262_144,
@ -19,7 +21,9 @@ const DIRECT_MODEL_CONTEXT_WINDOWS: Record<string, number> = {
'minimax-m3': 1_000_000,
'minimax-m2.7': 204_800,
'minimax-m2.7-highspeed': 204_800,
'glm-5.2': 200_000,
'qwen/qwen3.6-27b': 262_144,
'qwen3.6:27b': 262_144,
'glm-5.2': 1_000_000,
'glm-5.1': 200_000,
'glm-5': 200_000,
'glm-5-turbo': 200_000,
@ -37,11 +41,14 @@ const PATTERN_MODEL_CONTEXT_WINDOWS: Array<[RegExp, number]> = [
[/^openai\/gpt-5(?:[.-]\d+)?\b/i, 400_000],
[/^google\/gemini-(?:2\.0|2\.5|3)/i, 1_048_576],
[/^gemini-(?:2\.0|2\.5|3)/i, 1_048_576],
[/^zai-org\/glm-5\.2\b/i, 200_000],
[/^qwen\/qwen3\.5-(?:plus|flash)\b/i, 1_000_000],
[/^qwen3\.5-(?:plus|flash)\b/i, 1_000_000],
[/^qwen\/qwen3-max\b/i, 262_144],
[/^qwen3-max\b/i, 262_144],
[/^zai-org\/glm-5\.2\b/i, 1_000_000],
[/^(?:qwen\/)?qwen3\.7-(?:max|plus)(?:[-.][\w.-]+)?\b/i, 1_000_000],
[/^(?:qwen\/)?qwen3\.6-(?:plus|flash)(?:[-.][\w.-]+)?\b/i, 1_000_000],
[/^(?:qwen\/)?qwen3\.6-max-preview\b/i, 262_144],
[/^(?:qwen\/)?qwen3\.5-(?:plus|flash)(?:[-.][\w.-]+)?\b/i, 1_000_000],
[/^(?:qwen\/)?qwen3-max(?:[-.][\w.-]+)?\b/i, 262_144],
[/^(?:qwen\/)?qwen3-coder-plus(?:[-.][\w.-]+)?\b/i, 1_000_000],
[/^(?:qwen\/)?qwen3-coder-next(?:[-.][\w.-]+)?\b/i, 262_144],
[/qwen-long/i, 10_000_000],
]