mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-15 12:55:51 +00:00
refactor: 将 codex provider 重命名为 openai-responses
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import { describe, expect, test, beforeEach, afterEach } from 'bun:test'
|
||||
import { resolveCodexModel } from '../modelMapping.js'
|
||||
|
||||
describe('resolveCodexModel', () => {
|
||||
const originalEnv = {
|
||||
CODEX_MODEL: process.env.CODEX_MODEL,
|
||||
CODEX_DEFAULT_HAIKU_MODEL: process.env.CODEX_DEFAULT_HAIKU_MODEL,
|
||||
CODEX_DEFAULT_SONNET_MODEL: process.env.CODEX_DEFAULT_SONNET_MODEL,
|
||||
CODEX_DEFAULT_OPUS_MODEL: process.env.CODEX_DEFAULT_OPUS_MODEL,
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
delete process.env.CODEX_MODEL
|
||||
delete process.env.CODEX_DEFAULT_HAIKU_MODEL
|
||||
delete process.env.CODEX_DEFAULT_SONNET_MODEL
|
||||
delete process.env.CODEX_DEFAULT_OPUS_MODEL
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
Object.assign(process.env, originalEnv)
|
||||
})
|
||||
|
||||
test('CODEX_MODEL env var overrides all', () => {
|
||||
process.env.CODEX_MODEL = 'my-custom-model'
|
||||
expect(resolveCodexModel('claude-sonnet-4-6')).toBe('my-custom-model')
|
||||
})
|
||||
|
||||
test('CODEX_DEFAULT_SONNET_MODEL overrides default map', () => {
|
||||
process.env.CODEX_DEFAULT_SONNET_MODEL = 'my-sonnet'
|
||||
expect(resolveCodexModel('claude-sonnet-4-6')).toBe('my-sonnet')
|
||||
})
|
||||
|
||||
test('CODEX_DEFAULT_HAIKU_MODEL overrides default map', () => {
|
||||
process.env.CODEX_DEFAULT_HAIKU_MODEL = 'my-haiku'
|
||||
expect(resolveCodexModel('claude-haiku-4-5-20251001')).toBe('my-haiku')
|
||||
})
|
||||
|
||||
test('CODEX_DEFAULT_OPUS_MODEL overrides default map', () => {
|
||||
process.env.CODEX_DEFAULT_OPUS_MODEL = 'my-opus'
|
||||
expect(resolveCodexModel('claude-opus-4-6')).toBe('my-opus')
|
||||
})
|
||||
|
||||
test('maps known sonnet model via DEFAULT_MODEL_MAP', () => {
|
||||
expect(resolveCodexModel('claude-sonnet-4-6')).toBe('gpt-5.4-mini')
|
||||
})
|
||||
|
||||
test('maps known haiku model via DEFAULT_MODEL_MAP', () => {
|
||||
expect(resolveCodexModel('claude-haiku-4-5-20251001')).toBe('gpt-5.4-nano')
|
||||
})
|
||||
|
||||
test('maps known opus model via DEFAULT_MODEL_MAP', () => {
|
||||
expect(resolveCodexModel('claude-opus-4-6')).toBe('gpt-5.4')
|
||||
})
|
||||
|
||||
test('maps legacy sonnet models', () => {
|
||||
expect(resolveCodexModel('claude-sonnet-4-20250514')).toBe('gpt-5.4-mini')
|
||||
expect(resolveCodexModel('claude-3-5-sonnet-20241022')).toBe('gpt-5.4-mini')
|
||||
})
|
||||
|
||||
test('maps legacy haiku models', () => {
|
||||
expect(resolveCodexModel('claude-3-5-haiku-20241022')).toBe('gpt-5.4-nano')
|
||||
})
|
||||
|
||||
test('maps legacy opus models', () => {
|
||||
expect(resolveCodexModel('claude-opus-4-20250514')).toBe('gpt-5.4')
|
||||
expect(resolveCodexModel('claude-opus-4-5-20251101')).toBe('gpt-5.4')
|
||||
})
|
||||
|
||||
test('uses family default for unrecognized haiku model', () => {
|
||||
expect(resolveCodexModel('claude-haiku-99')).toBe('gpt-5.4-nano')
|
||||
})
|
||||
|
||||
test('uses family default for unrecognized sonnet model', () => {
|
||||
expect(resolveCodexModel('claude-sonnet-99')).toBe('gpt-5.4-mini')
|
||||
})
|
||||
|
||||
test('uses family default for unrecognized opus model', () => {
|
||||
expect(resolveCodexModel('claude-opus-99')).toBe('gpt-5.4')
|
||||
})
|
||||
|
||||
test('passes through unknown model name without family', () => {
|
||||
expect(resolveCodexModel('some-random-model')).toBe('some-random-model')
|
||||
})
|
||||
|
||||
test('strips [1m] suffix', () => {
|
||||
expect(resolveCodexModel('claude-sonnet-4-6[1m]')).toBe('gpt-5.4-mini')
|
||||
})
|
||||
|
||||
test('CODEX_MODEL takes precedence over family-specific vars', () => {
|
||||
process.env.CODEX_MODEL = 'global-override'
|
||||
process.env.CODEX_DEFAULT_SONNET_MODEL = 'family-override'
|
||||
expect(resolveCodexModel('claude-sonnet-4-6')).toBe('global-override')
|
||||
})
|
||||
})
|
||||
@@ -1,3 +1,30 @@
|
||||
/**
|
||||
* Default mapping from Anthropic model names to Codex (OpenAI Responses API) model names.
|
||||
* Used only when CODEX_DEFAULT_{FAMILY}_MODEL env vars are not set.
|
||||
*/
|
||||
const DEFAULT_MODEL_MAP: Record<string, string> = {
|
||||
'claude-sonnet-4-20250514': 'gpt-5.4-mini',
|
||||
'claude-sonnet-4-5-20250929': 'gpt-5.4-mini',
|
||||
'claude-sonnet-4-6': 'gpt-5.4-mini',
|
||||
'claude-3-7-sonnet-20250219': 'gpt-5.4-mini',
|
||||
'claude-3-5-sonnet-20241022': 'gpt-5.4-mini',
|
||||
'claude-opus-4-20250514': 'gpt-5.4',
|
||||
'claude-opus-4-1-20250805': 'gpt-5.4',
|
||||
'claude-opus-4-5-20251101': 'gpt-5.4',
|
||||
'claude-opus-4-6': 'gpt-5.4',
|
||||
'claude-haiku-4-5-20251001': 'gpt-5.4-nano',
|
||||
'claude-3-5-haiku-20241022': 'gpt-5.4-nano',
|
||||
}
|
||||
|
||||
/**
|
||||
* Default model for each family when an exact match is not in DEFAULT_MODEL_MAP.
|
||||
*/
|
||||
const DEFAULT_FAMILY_MAP: Record<string, string> = {
|
||||
haiku: 'gpt-5.4-nano',
|
||||
sonnet: 'gpt-5.4-mini',
|
||||
opus: 'gpt-5.4',
|
||||
}
|
||||
|
||||
function getModelFamily(model: string): 'haiku' | 'sonnet' | 'opus' | null {
|
||||
if (/haiku/i.test(model)) return 'haiku'
|
||||
if (/opus/i.test(model)) return 'opus'
|
||||
@@ -5,6 +32,16 @@ function getModelFamily(model: string): 'haiku' | 'sonnet' | 'opus' | null {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the Codex (OpenAI Responses API) model name for a given Anthropic model.
|
||||
*
|
||||
* Priority:
|
||||
* 1. CODEX_MODEL env var (override all)
|
||||
* 2. CODEX_DEFAULT_{FAMILY}_MODEL env var (e.g. CODEX_DEFAULT_SONNET_MODEL)
|
||||
* 3. DEFAULT_MODEL_MAP lookup (exact Anthropic model name match)
|
||||
* 4. DEFAULT_FAMILY_MAP lookup (family-based default)
|
||||
* 5. Pass through original model name
|
||||
*/
|
||||
export function resolveCodexModel(model: string): string {
|
||||
if (process.env.CODEX_MODEL) {
|
||||
return process.env.CODEX_MODEL
|
||||
@@ -19,6 +56,15 @@ export function resolveCodexModel(model: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
const mapped = DEFAULT_MODEL_MAP[cleanModel]
|
||||
if (mapped) {
|
||||
return mapped
|
||||
}
|
||||
|
||||
if (family) {
|
||||
return DEFAULT_FAMILY_MAP[family]
|
||||
}
|
||||
|
||||
return cleanModel
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user