diff --git a/shared/modelConstants.js b/shared/modelConstants.js index ae42ed2..1631acf 100644 --- a/shared/modelConstants.js +++ b/shared/modelConstants.js @@ -1,28 +1,40 @@ /** * Centralized Model Definitions * Single source of truth for all supported AI models + * + * IMPORTANT: Claude model values must be the exact string accepted by the + * Claude Code SDK's `options.model` field. When routing through 9router, + * models are prefixed with "cc/" (e.g. "cc/claude-sonnet-4-6"). + * The DEFAULT is used as the initial localStorage value and as the SDK + * fallback when the user has not selected a model. */ /** - * Claude (Anthropic) Models + * Claude (Anthropic / 9router) Models * - * Note: Claude uses two different formats: - * - SDK format ('sonnet', 'opus') - used by the UI and claude-sdk.js - * - API format ('claude-sonnet-4.5') - used by slash commands for display + * When ANTHROPIC_BASE_URL points at 9router the model IDs must include the + * "cc/" namespace prefix that 9router adds. The frontend fetches the live + * list from /api/models and uses these constants only as the static fallback. */ export const CLAUDE_MODELS = { - // Models in SDK format (what the actual SDK accepts) + // Static fallback list — used when /api/models is unreachable. + // Values must match exactly what the Claude Code SDK (or 9router) accepts. OPTIONS: [ - { value: "opus", label: "Opus" }, - { value: "sonnet", label: "Sonnet" }, - { value: "haiku", label: "Haiku" }, - { value: "claude-opus-4-6", label: "Opus 4.6" }, - { value: "opusplan", label: "Opus Plan" }, - { value: "sonnet[1m]", label: "Sonnet [1M]" }, - { value: "opus[1m]", label: "Opus [1M]" }, + // 9router namespaced IDs (preferred when ANTHROPIC_BASE_URL is set) + { value: "cc/claude-sonnet-4-6", label: "Claude Sonnet 4.6 (9router)" }, + { value: "cc/claude-opus-4-5", label: "Claude Opus 4.5 (9router)" }, + { value: "cc/claude-haiku-3-5", label: "Claude Haiku 3.5 (9router)" }, + // Direct Anthropic SDK aliases (used when hitting Anthropic directly) + { value: "sonnet", label: "Sonnet (latest)" }, + { value: "opus", label: "Opus (latest)" }, + { value: "haiku", label: "Haiku (latest)" }, + { value: "sonnet[1m]", label: "Sonnet [1M ctx]" }, + { value: "opus[1m]", label: "Opus [1M ctx]" }, ], - DEFAULT: "opus", + // Default selected model — prefer 9router cc/ model when available. + // Can be overridden at runtime from localStorage("claude-model"). + DEFAULT: "cc/claude-sonnet-4-6", }; /** @@ -30,25 +42,25 @@ export const CLAUDE_MODELS = { */ export const CURSOR_MODELS = { OPTIONS: [ - { value: "opus-4.6-thinking", label: "Claude 4.6 Opus (Thinking)" }, - { value: "gpt-5.3-codex", label: "GPT-5.3" }, - { value: "gpt-5.2-high", label: "GPT-5.2 High" }, - { value: "gemini-3-pro", label: "Gemini 3 Pro" }, - { value: "opus-4.5-thinking", label: "Claude 4.5 Opus (Thinking)" }, - { value: "gpt-5.2", label: "GPT-5.2" }, - { value: "gpt-5.1", label: "GPT-5.1" }, - { value: "gpt-5.1-high", label: "GPT-5.1 High" }, - { value: "composer-1", label: "Composer 1" }, - { value: "auto", label: "Auto" }, - { value: "sonnet-4.5", label: "Claude 4.5 Sonnet" }, - { value: "sonnet-4.5-thinking", label: "Claude 4.5 Sonnet (Thinking)" }, - { value: "opus-4.5", label: "Claude 4.5 Opus" }, - { value: "gpt-5.1-codex", label: "GPT-5.1 Codex" }, - { value: "gpt-5.1-codex-high", label: "GPT-5.1 Codex High" }, - { value: "gpt-5.1-codex-max", label: "GPT-5.1 Codex Max" }, - { value: "gpt-5.1-codex-max-high", label: "GPT-5.1 Codex Max High" }, - { value: "opus-4.1", label: "Claude 4.1 Opus" }, - { value: "grok", label: "Grok" }, + { value: "opus-4.6-thinking", label: "Claude 4.6 Opus (Thinking)" }, + { value: "gpt-5.3-codex", label: "GPT-5.3" }, + { value: "gpt-5.2-high", label: "GPT-5.2 High" }, + { value: "gemini-3-pro", label: "Gemini 3 Pro" }, + { value: "opus-4.5-thinking", label: "Claude 4.5 Opus (Thinking)" }, + { value: "gpt-5.2", label: "GPT-5.2" }, + { value: "gpt-5.1", label: "GPT-5.1" }, + { value: "gpt-5.1-high", label: "GPT-5.1 High" }, + { value: "composer-1", label: "Composer 1" }, + { value: "auto", label: "Auto" }, + { value: "sonnet-4.5", label: "Claude 4.5 Sonnet" }, + { value: "sonnet-4.5-thinking", label: "Claude 4.5 Sonnet (Thinking)"}, + { value: "opus-4.5", label: "Claude 4.5 Opus" }, + { value: "gpt-5.1-codex", label: "GPT-5.1 Codex" }, + { value: "gpt-5.1-codex-high", label: "GPT-5.1 Codex High" }, + { value: "gpt-5.1-codex-max", label: "GPT-5.1 Codex Max" }, + { value: "gpt-5.1-codex-max-high", label: "GPT-5.1 Codex Max High" }, + { value: "opus-4.1", label: "Claude 4.1 Opus" }, + { value: "grok", label: "Grok" }, ], DEFAULT: "gpt-5.3-codex", @@ -59,15 +71,15 @@ export const CURSOR_MODELS = { */ export const CODEX_MODELS = { OPTIONS: [ - { value: "gpt-5.5", label: "GPT-5.5" }, - { value: "gpt-5.4", label: "GPT-5.4" }, - { value: "gpt-5.4-mini", label: "GPT-5.4 mini" }, - { value: "gpt-5.3-codex", label: "GPT-5.3 Codex" }, - { value: "gpt-5.2-codex", label: "GPT-5.2 Codex" }, - { value: "gpt-5.2", label: "GPT-5.2" }, - { value: "gpt-5.1-codex-max", label: "GPT-5.1 Codex Max" }, - { value: "o3", label: "O3" }, - { value: "o4-mini", label: "O4-mini" }, + { value: "gpt-5.5", label: "GPT-5.5" }, + { value: "gpt-5.4", label: "GPT-5.4" }, + { value: "gpt-5.4-mini", label: "GPT-5.4 mini" }, + { value: "gpt-5.3-codex", label: "GPT-5.3 Codex" }, + { value: "gpt-5.2-codex", label: "GPT-5.2 Codex" }, + { value: "gpt-5.2", label: "GPT-5.2" }, + { value: "gpt-5.1-codex-max", label: "GPT-5.1 Codex Max"}, + { value: "o3", label: "O3" }, + { value: "o4-mini", label: "O4-mini" }, ], DEFAULT: "gpt-5.4", @@ -78,19 +90,16 @@ export const CODEX_MODELS = { */ export const GEMINI_MODELS = { OPTIONS: [ - { value: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro Preview" }, - { value: "gemini-3-pro-preview", label: "Gemini 3 Pro Preview" }, - { value: "gemini-3-flash-preview", label: "Gemini 3 Flash Preview" }, - { value: "gemini-2.5-flash", label: "Gemini 2.5 Flash" }, - { value: "gemini-2.5-pro", label: "Gemini 2.5 Pro" }, - { value: "gemini-2.0-flash-lite", label: "Gemini 2.0 Flash Lite" }, - { value: "gemini-2.5-flash-lite", label: "Gemini 2.5 Flash Lite" }, - { value: "gemini-2.0-flash", label: "Gemini 2.0 Flash" }, - { value: "gemini-2.0-pro-exp", label: "Gemini 2.0 Pro Experimental" }, - { - value: "gemini-2.0-flash-thinking-exp", - label: "Gemini 2.0 Flash Thinking", - }, + { value: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro Preview" }, + { value: "gemini-3-pro-preview", label: "Gemini 3 Pro Preview" }, + { value: "gemini-3-flash-preview", label: "Gemini 3 Flash Preview" }, + { value: "gemini-2.5-flash", label: "Gemini 2.5 Flash" }, + { value: "gemini-2.5-pro", label: "Gemini 2.5 Pro" }, + { value: "gemini-2.0-flash-lite", label: "Gemini 2.0 Flash Lite" }, + { value: "gemini-2.5-flash-lite", label: "Gemini 2.5 Flash Lite" }, + { value: "gemini-2.0-flash", label: "Gemini 2.0 Flash" }, + { value: "gemini-2.0-pro-exp", label: "Gemini 2.0 Pro Experimental" }, + { value: "gemini-2.0-flash-thinking-exp", label: "Gemini 2.0 Flash Thinking" }, ], DEFAULT: "gemini-3.1-pro-preview", @@ -101,7 +110,7 @@ export const GEMINI_MODELS = { */ export const PROVIDERS = [ { id: "claude", name: "Anthropic", models: CLAUDE_MODELS }, - { id: "codex", name: "OpenAI", models: CODEX_MODELS }, - { id: "gemini", name: "Google", models: GEMINI_MODELS }, - { id: "cursor", name: "Cursor", models: CURSOR_MODELS }, + { id: "codex", name: "OpenAI", models: CODEX_MODELS }, + { id: "gemini", name: "Google", models: GEMINI_MODELS }, + { id: "cursor", name: "Cursor", models: CURSOR_MODELS }, ];