| ... | @@ -1,23 +1,72 @@ | ... | @@ -1,23 +1,72 @@ |
| 1 | export const MODEL_OPTIONS = [ | 1 | import type { ProviderKind } from "./orchestration"; |
| 2 | { slug: "gpt-5.3-codex", name: "GPT-5.3 Codex" }, | 2 | |
| 3 | { slug: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark" }, | 3 | type ModelOption = { |
| 4 | { slug: "gpt-5.2-codex", name: "GPT-5.2 Codex" }, | 4 | readonly slug: string; |
| 5 | { slug: "gpt-5.2", name: "GPT-5.2" }, | 5 | readonly name: string; |
| 6 | ] as const; | 6 | }; |
| 7 | | 7 | |
| 8 | export type BuiltInModelSlug = (typeof MODEL_OPTIONS)[number]["slug"]; | 8 | export const MODEL_OPTIONS_BY_PROVIDER = { |
| 9 | export type ModelSlug = string; | 9 | codex: [ |
| 10 | | 10 | { slug: "gpt-5.3-codex", name: "GPT-5.3 Codex" }, |
| 11 | export const DEFAULT_MODEL = "gpt-5.3-codex"; | 11 | { slug: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark" }, |
| 12 | | 12 | { slug: "gpt-5.2-codex", name: "GPT-5.2 Codex" }, |
| 13 | export const MODEL_SLUG_ALIASES: Record<string, BuiltInModelSlug> = { | 13 | { slug: "gpt-5.2", name: "GPT-5.2" }, |
| 14 | "5.3": "gpt-5.3-codex", | 14 | ], |
| 15 | "gpt-5.3": "gpt-5.3-codex", | 15 | claudeCode: [ |
| 16 | "5.3-spark": "gpt-5.3-codex-spark", | 16 | { slug: "claude-sonnet-4-5", name: "Claude Sonnet 4.5" }, |
| 17 | "gpt-5.3-spark": "gpt-5.3-codex-spark", | 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 | if (typeof model !== "string") { | 70 | if (typeof model !== "string") { |
| 22 | return null; | 71 | return null; |
| 23 | } | 72 | } |
| ... | @@ -27,12 +76,28 @@ export function normalizeModelSlug(model: string | null | undefined): ModelSlug | ... | @@ -27,12 +76,28 @@ export function normalizeModelSlug(model: string | null | undefined): ModelSlug |
| 27 | return null; | 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 { | 96 | export function resolveModelSlugForProvider( |
| 34 | const normalized = normalizeModelSlug(model); | 97 | provider: ProviderKind, |
| 35 | return normalized ?? DEFAULT_MODEL; | 98 | model: string | null | undefined, |
| | 99 | ): ModelSlug { |
| | 100 | return resolveModelSlug(model, provider); |
| 36 | } | 101 | } |
| 37 | | 102 | |
| 38 | export const REASONING_OPTIONS = ["xhigh", "high", "medium", "low"] as const; | 103 | export const REASONING_OPTIONS = ["xhigh", "high", "medium", "low"] as const; |