| ... | ... | @@ -1,23 +1,72 @@ |
| 1 | | export const MODEL_OPTIONS = [ |
| 2 | | { slug: "gpt-5.3-codex", name: "GPT-5.3 Codex" }, |
| 3 | | { slug: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark" }, |
| 4 | | { slug: "gpt-5.2-codex", name: "GPT-5.2 Codex" }, |
| 5 | | { slug: "gpt-5.2", name: "GPT-5.2" }, |
| 6 | | ] as const; |
| 7 | | |
| 8 | | export type BuiltInModelSlug = (typeof MODEL_OPTIONS)[number]["slug"]; |
| 9 | | export type ModelSlug = string; |
| 10 | | |
| 11 | | export const DEFAULT_MODEL = "gpt-5.3-codex"; |
| 12 | | |
| 13 | | export const MODEL_SLUG_ALIASES: Record<string, BuiltInModelSlug> = { |
| 14 | | "5.3": "gpt-5.3-codex", |
| 15 | | "gpt-5.3": "gpt-5.3-codex", |
| 16 | | "5.3-spark": "gpt-5.3-codex-spark", |
| 17 | | "gpt-5.3-spark": "gpt-5.3-codex-spark", |
| 1 | import type { ProviderKind } from "./orchestration"; |
| 2 | |
| 3 | type ModelOption = { |
| 4 | readonly slug: string; |
| 5 | readonly name: string; |
| 6 | }; |
| 7 | |
| 8 | export const MODEL_OPTIONS_BY_PROVIDER = { |
| 9 | codex: [ |
| 10 | { slug: "gpt-5.3-codex", name: "GPT-5.3 Codex" }, |
| 11 | { slug: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark" }, |
| 12 | { slug: "gpt-5.2-codex", name: "GPT-5.2 Codex" }, |
| 13 | { slug: "gpt-5.2", name: "GPT-5.2" }, |
| 14 | ], |
| 15 | claudeCode: [ |
| 16 | { slug: "claude-sonnet-4-5", name: "Claude Sonnet 4.5" }, |
| 17 | { slug: "claude-opus-4-1", name: "Claude Opus 4.1" }, |
| 18 | { slug: "claude-haiku-3-5", name: "Claude Haiku 3.5" }, |
| 19 | ], |
| 20 | } as const satisfies Record<ProviderKind, readonly ModelOption[]>; |
| 21 | |
| 22 | export type ModelSlug = (typeof MODEL_OPTIONS_BY_PROVIDER)[ProviderKind][number]["slug"]; |
| 23 | |
| 24 | export const DEFAULT_MODEL_BY_PROVIDER: Record<ProviderKind, ModelSlug> = { |
| 25 | codex: "gpt-5.3-codex", |
| 26 | claudeCode: "claude-sonnet-4-5", |
| 27 | }; |
| 28 | |
| 29 | // Backward compatibility for existing Codex-only call sites. |
| 30 | export const MODEL_OPTIONS = MODEL_OPTIONS_BY_PROVIDER.codex; |
| 31 | export const DEFAULT_MODEL = DEFAULT_MODEL_BY_PROVIDER.codex; |
| 32 | |
| 33 | export const MODEL_SLUG_ALIASES_BY_PROVIDER: Record<ProviderKind, Record<string, ModelSlug>> = { |
| 34 | codex: { |
| 35 | "5.3": "gpt-5.3-codex", |
| 36 | "gpt-5.3": "gpt-5.3-codex", |
| 37 | "5.3-spark": "gpt-5.3-codex-spark", |
| 38 | "gpt-5.3-spark": "gpt-5.3-codex-spark", |
| 39 | }, |
| 40 | claudeCode: { |
| 41 | sonnet: "claude-sonnet-4-5", |
| 42 | "sonnet-4.5": "claude-sonnet-4-5", |
| 43 | "claude-sonnet-4.5": "claude-sonnet-4-5", |
| 44 | opus: "claude-opus-4-1", |
| 45 | "opus-4.1": "claude-opus-4-1", |
| 46 | "claude-opus-4.1": "claude-opus-4-1", |
| 47 | haiku: "claude-haiku-3-5", |
| 48 | "haiku-3.5": "claude-haiku-3-5", |
| 49 | "claude-haiku-3.5": "claude-haiku-3-5", |
| 50 | }, |
| 51 | }; |
| 52 | |
| 53 | const MODEL_SLUG_SET_BY_PROVIDER: Record<ProviderKind, ReadonlySet<ModelSlug>> = { |
| 54 | codex: new Set(MODEL_OPTIONS_BY_PROVIDER.codex.map((option) => option.slug)), |
| 55 | claudeCode: new Set(MODEL_OPTIONS_BY_PROVIDER.claudeCode.map((option) => option.slug)), |
| 18 | 56 | }; |
| 19 | 57 | |
| 20 | | export function normalizeModelSlug(model: string | null | undefined): ModelSlug | null { |
| 58 | export function getModelOptions(provider: ProviderKind = "codex") { |
| 59 | return MODEL_OPTIONS_BY_PROVIDER[provider]; |
| 60 | } |
| 61 | |
| 62 | export function getDefaultModel(provider: ProviderKind = "codex"): ModelSlug { |
| 63 | return DEFAULT_MODEL_BY_PROVIDER[provider]; |
| 64 | } |
| 65 | |
| 66 | export function normalizeModelSlug( |
| 67 | model: string | null | undefined, |
| 68 | provider: ProviderKind = "codex", |
| 69 | ): ModelSlug | null { |
| 21 | 70 | if (typeof model !== "string") { |
| 22 | 71 | return null; |
| 23 | 72 | } |
| ... | ... | @@ -27,12 +76,28 @@ export function normalizeModelSlug(model: string | null | undefined): ModelSlug |
| 27 | 76 | return null; |
| 28 | 77 | } |
| 29 | 78 | |
| 30 | | return MODEL_SLUG_ALIASES[trimmed] ?? trimmed; |
| 79 | return MODEL_SLUG_ALIASES_BY_PROVIDER[provider][trimmed] ?? (trimmed as ModelSlug); |
| 80 | } |
| 81 | |
| 82 | export function resolveModelSlug( |
| 83 | model: string | null | undefined, |
| 84 | provider: ProviderKind = "codex", |
| 85 | ): ModelSlug { |
| 86 | const normalized = normalizeModelSlug(model, provider); |
| 87 | if (!normalized) { |
| 88 | return DEFAULT_MODEL_BY_PROVIDER[provider]; |
| 89 | } |
| 90 | |
| 91 | return MODEL_SLUG_SET_BY_PROVIDER[provider].has(normalized) |
| 92 | ? normalized |
| 93 | : DEFAULT_MODEL_BY_PROVIDER[provider]; |
| 31 | 94 | } |
| 32 | 95 | |
| 33 | | export function resolveModelSlug(model: string | null | undefined): ModelSlug { |
| 34 | | const normalized = normalizeModelSlug(model); |
| 35 | | return normalized ?? DEFAULT_MODEL; |
| 96 | export function resolveModelSlugForProvider( |
| 97 | provider: ProviderKind, |
| 98 | model: string | null | undefined, |
| 99 | ): ModelSlug { |
| 100 | return resolveModelSlug(model, provider); |
| 36 | 101 | } |
| 37 | 102 | |
| 38 | 103 | export const REASONING_OPTIONS = ["xhigh", "high", "medium", "low"] as const; |