gemini模型环境变量分离 provider指令支持切换gemini

This commit is contained in:
HitMargin
2026-04-06 11:23:05 +08:00
parent 6f80e96fee
commit 14dc54a093
9 changed files with 324 additions and 47 deletions

View File

@@ -4,6 +4,9 @@ import { resolveGeminiModel } from '../modelMapping.js'
describe('resolveGeminiModel', () => {
const originalEnv = {
GEMINI_MODEL: process.env.GEMINI_MODEL,
GEMINI_DEFAULT_HAIKU_MODEL: process.env.GEMINI_DEFAULT_HAIKU_MODEL,
GEMINI_DEFAULT_SONNET_MODEL: process.env.GEMINI_DEFAULT_SONNET_MODEL,
GEMINI_DEFAULT_OPUS_MODEL: process.env.GEMINI_DEFAULT_OPUS_MODEL,
ANTHROPIC_DEFAULT_HAIKU_MODEL: process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL,
ANTHROPIC_DEFAULT_SONNET_MODEL: process.env.ANTHROPIC_DEFAULT_SONNET_MODEL,
ANTHROPIC_DEFAULT_OPUS_MODEL: process.env.ANTHROPIC_DEFAULT_OPUS_MODEL,
@@ -11,6 +14,9 @@ describe('resolveGeminiModel', () => {
beforeEach(() => {
delete process.env.GEMINI_MODEL
delete process.env.GEMINI_DEFAULT_HAIKU_MODEL
delete process.env.GEMINI_DEFAULT_SONNET_MODEL
delete process.env.GEMINI_DEFAULT_OPUS_MODEL
delete process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL
delete process.env.ANTHROPIC_DEFAULT_SONNET_MODEL
delete process.env.ANTHROPIC_DEFAULT_OPUS_MODEL
@@ -27,35 +33,57 @@ describe('resolveGeminiModel', () => {
expect(resolveGeminiModel('claude-sonnet-4-6')).toBe('gemini-2.5-pro')
})
test('resolves sonnet model from shared family override', () => {
test('GEMINI_DEFAULT_*_MODEL takes precedence over ANTHROPIC_DEFAULT_*', () => {
process.env.GEMINI_DEFAULT_SONNET_MODEL = 'gemini-2.5-flash-priority'
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL = 'gemini-2.5-flash-fallback'
expect(resolveGeminiModel('claude-sonnet-4-6')).toBe(
'gemini-2.5-flash-priority',
)
})
test('resolves sonnet model from GEMINI_DEFAULT_SONNET_MODEL', () => {
process.env.GEMINI_DEFAULT_SONNET_MODEL = 'gemini-2.5-flash'
expect(resolveGeminiModel('claude-sonnet-4-6')).toBe('gemini-2.5-flash')
})
test('resolves haiku model from GEMINI_DEFAULT_HAIKU_MODEL', () => {
process.env.GEMINI_DEFAULT_HAIKU_MODEL = 'gemini-2.5-flash-lite'
expect(resolveGeminiModel('claude-haiku-4-5-20251001')).toBe(
'gemini-2.5-flash-lite',
)
})
test('resolves opus model from GEMINI_DEFAULT_OPUS_MODEL', () => {
process.env.GEMINI_DEFAULT_OPUS_MODEL = 'gemini-2.5-pro'
expect(resolveGeminiModel('claude-opus-4-6')).toBe('gemini-2.5-pro')
})
test('falls back to ANTHROPIC_DEFAULT_* when GEMINI_DEFAULT_* not set', () => {
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL = 'gemini-2.5-flash'
expect(resolveGeminiModel('claude-sonnet-4-6')).toBe('gemini-2.5-flash')
})
test('resolves haiku model from shared family override', () => {
test('resolves haiku from ANTHROPIC_DEFAULT_HAIKU_MODEL as fallback', () => {
process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL = 'gemini-2.5-flash-lite'
expect(resolveGeminiModel('claude-haiku-4-5-20251001')).toBe(
'gemini-2.5-flash-lite',
)
})
test('resolves opus model from shared family override', () => {
test('resolves opus from ANTHROPIC_DEFAULT_OPUS_MODEL as fallback', () => {
process.env.ANTHROPIC_DEFAULT_OPUS_MODEL = 'gemini-2.5-pro'
expect(resolveGeminiModel('claude-opus-4-6')).toBe('gemini-2.5-pro')
})
test('uses shared family override', () => {
test('uses backward compatible family override', () => {
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL = 'legacy-gemini-sonnet'
expect(resolveGeminiModel('claude-sonnet-4-6')).toBe(
'legacy-gemini-sonnet',
)
expect(resolveGeminiModel('claude-sonnet-4-6')).toBe('legacy-gemini-sonnet')
})
test('strips [1m] suffix before resolving', () => {
process.env.ANTHROPIC_DEFAULT_SONNET_MODEL = 'gemini-2.5-flash'
expect(resolveGeminiModel('claude-sonnet-4-6[1m]')).toBe(
'gemini-2.5-flash',
)
process.env.GEMINI_DEFAULT_SONNET_MODEL = 'gemini-2.5-flash'
expect(resolveGeminiModel('claude-sonnet-4-6[1m]')).toBe('gemini-2.5-flash')
})
test('passes through explicit Gemini model names', () => {
@@ -64,9 +92,9 @@ describe('resolveGeminiModel', () => {
)
})
test('throws when family mapping is missing', () => {
test('throws when no Gemini model configuration is available', () => {
expect(() => resolveGeminiModel('claude-sonnet-4-6')).toThrow(
'Gemini provider requires GEMINI_MODEL or ANTHROPIC_DEFAULT_SONNET_MODEL to be configured.',
'Gemini provider requires GEMINI_MODEL or GEMINI_DEFAULT_SONNET_MODEL (or ANTHROPIC_DEFAULT_SONNET_MODEL for backward compatibility) to be configured.',
)
})
})

View File

@@ -17,6 +17,14 @@ export function resolveGeminiModel(anthropicModel: string): string {
return cleanModel
}
// First, try Gemini-specific DEFAULT variables (separated from Anthropic)
const geminiEnvVar = `GEMINI_DEFAULT_${family.toUpperCase()}_MODEL`
const geminiModel = process.env[geminiEnvVar]
if (geminiModel) {
return geminiModel
}
// Fallback to Anthropic DEFAULT variables for backward compatibility
const sharedEnvVar = `ANTHROPIC_DEFAULT_${family.toUpperCase()}_MODEL`
const resolvedModel = process.env[sharedEnvVar]
if (resolvedModel) {
@@ -24,7 +32,6 @@ export function resolveGeminiModel(anthropicModel: string): string {
}
throw new Error(
`Gemini provider requires GEMINI_MODEL or ${sharedEnvVar} to be configured.`,
`Gemini provider requires GEMINI_MODEL or ${geminiEnvVar} (or ${sharedEnvVar} for backward compatibility) to be configured.`,
)
}