diff --git a/crates/language_models/src/provider/opencode.rs b/crates/language_models/src/provider/opencode.rs index 2a4e27c3c7ce78..f5281e019f71ec 100644 --- a/crates/language_models/src/provider/opencode.rs +++ b/crates/language_models/src/provider/opencode.rs @@ -72,7 +72,6 @@ pub struct OpenCodeSettings { pub custom_headers: CustomHeaders, pub show_zen_models: bool, pub show_go_models: bool, - pub show_free_models: bool, } pub struct OpenCodeLanguageModelProvider { @@ -167,7 +166,6 @@ impl OpenCodeLanguageModelProvider { match subscription { OpenCodeSubscription::Zen => settings.show_zen_models, OpenCodeSubscription::Go => settings.show_go_models, - OpenCodeSubscription::Free => settings.show_free_models, } } @@ -210,13 +208,6 @@ impl LanguageModelProvider for OpenCodeLanguageModelProvider { ) } else if Self::subscription_enabled(OpenCodeSubscription::Zen, cx) { Some(self.create_language_model(opencode::Model::default(), OpenCodeSubscription::Zen)) - } else if Self::subscription_enabled(OpenCodeSubscription::Free, cx) { - Some( - self.create_language_model( - opencode::Model::default_free(), - OpenCodeSubscription::Free, - ), - ) } else { None } @@ -236,11 +227,6 @@ impl LanguageModelProvider for OpenCodeLanguageModelProvider { OpenCodeSubscription::Zen, ), ) - } else if Self::subscription_enabled(OpenCodeSubscription::Free, cx) { - Some(self.create_language_model( - opencode::Model::default_free_fast(), - OpenCodeSubscription::Free, - )) } else { None } @@ -273,7 +259,6 @@ impl LanguageModelProvider for OpenCodeLanguageModelProvider { }; let subscription = match model.subscription { Some(settings::OpenCodeModelSubscription::Go) => OpenCodeSubscription::Go, - Some(settings::OpenCodeModelSubscription::Free) => OpenCodeSubscription::Free, Some(settings::OpenCodeModelSubscription::Zen) | None => OpenCodeSubscription::Zen, }; if !Self::subscription_enabled(subscription, cx) { @@ -858,7 +843,6 @@ impl ConfigurationView { match subscription { OpenCodeSubscription::Zen => opencode_settings.show_zen_models = Some(is_enabled), OpenCodeSubscription::Go => opencode_settings.show_go_models = Some(is_enabled), - OpenCodeSubscription::Free => opencode_settings.show_free_models = Some(is_enabled), } }); } @@ -935,7 +919,6 @@ impl Render for ConfigurationView { let settings = OpenCodeLanguageModelProvider::settings(cx); let show_zen = settings.show_zen_models; let show_go = settings.show_go_models; - let show_free = settings.show_free_models; let subscription_toggles = v_flex() .gap_2() @@ -943,7 +926,7 @@ impl Render for ConfigurationView { .child( Switch::new("opencode-show-zen-models", show_zen.into()) .full_width(true) - .label("Show Zen Models") + .label("Show Zen models") .label_position(SwitchLabelPosition::Start) .on_click(cx.listener(|this, state, window, cx| { this.set_subscription_enabled( @@ -968,24 +951,9 @@ impl Render for ConfigurationView { cx, ); })), - ) - .child(Divider::horizontal_dashed()) - .child( - Switch::new("opencode-show-free-models", show_free.into()) - .full_width(true) - .label("Show Free models") - .label_position(SwitchLabelPosition::Start) - .on_click(cx.listener(|this, state, window, cx| { - this.set_subscription_enabled( - OpenCodeSubscription::Free, - matches!(state, ToggleState::Selected), - window, - cx, - ); - })), ); - let no_subscriptions_warning = if !show_zen && !show_go && !show_free { + let no_subscriptions_warning = if !show_zen && !show_go { Some(Banner::new().severity(Severity::Warning).child(Label::new( "No subscriptions enabled. Enable at least one subscription to use OpenCode.", ))) diff --git a/crates/language_models/src/settings.rs b/crates/language_models/src/settings.rs index 4f360eea95c845..7868b3f16605e7 100644 --- a/crates/language_models/src/settings.rs +++ b/crates/language_models/src/settings.rs @@ -158,7 +158,6 @@ impl settings::Settings for AllLanguageModelSettings { ), show_zen_models: opencode.show_zen_models.unwrap_or(true), show_go_models: opencode.show_go_models.unwrap_or(true), - show_free_models: opencode.show_free_models.unwrap_or(true), }, open_router: OpenRouterSettings { api_url: open_router.api_url.unwrap(), diff --git a/crates/opencode/src/opencode.rs b/crates/opencode/src/opencode.rs index 9558bc8f24b8e5..8e7f998b376790 100644 --- a/crates/opencode/src/opencode.rs +++ b/crates/opencode/src/opencode.rs @@ -26,7 +26,6 @@ pub enum ApiProtocol { pub enum OpenCodeSubscription { Zen, Go, - Free, } impl OpenCodeSubscription { @@ -34,7 +33,6 @@ impl OpenCodeSubscription { match self { Self::Zen => "Zen", Self::Go => "Go", - Self::Free => "Free", } } @@ -42,13 +40,12 @@ impl OpenCodeSubscription { match self { Self::Zen => "zen", Self::Go => "go", - Self::Free => "free", } } pub fn api_path_suffix(&self) -> &'static str { match self { - Self::Zen | Self::Free => "", + Self::Zen => "", Self::Go => "/go", } } @@ -58,6 +55,8 @@ impl OpenCodeSubscription { #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, EnumIter)] pub enum Model { // -- Anthropic protocol models -- + #[serde(rename = "claude-opus-5")] + ClaudeOpus5, #[serde(rename = "claude-opus-4-8")] ClaudeOpus4_8, #[serde(rename = "claude-opus-4-7")] @@ -66,8 +65,6 @@ pub enum Model { ClaudeOpus4_6, #[serde(rename = "claude-opus-4-5")] ClaudeOpus4_5, - #[serde(rename = "claude-opus-4-1")] - ClaudeOpus4_1, #[default] #[serde(rename = "claude-sonnet-4-6")] ClaudeSonnet4_6, @@ -129,8 +126,14 @@ pub enum Model { Gemini3_1Pro, #[serde(rename = "gemini-3-flash")] Gemini3Flash, + #[serde(rename = "gemini-3.5-flash-lite")] + Gemini3_5FlashLite, #[serde(rename = "gemini-3.5-flash")] Gemini3_5Flash, + #[serde(rename = "gemini-3.6-flash")] + Gemini3_6Flash, + #[serde(rename = "gemini-3.7-flash")] + Gemini3_7Flash, // -- OpenAI Chat Completions protocol models -- #[serde(rename = "deepseek-v4-pro")] @@ -145,16 +148,24 @@ pub enum Model { Glm5_1, #[serde(rename = "glm-5.2")] Glm5_2, + #[serde(rename = "glm-5.3")] + Glm5_3, #[serde(rename = "grok-build-0.1")] GrokBuild0_1, #[serde(rename = "grok-4.5")] Grok4_5, + #[serde(rename = "grok-4.6")] + Grok4_6, + #[serde(rename = "muse-spark-1.2")] + MuseSpark1_2, #[serde(rename = "kimi-k2.5")] KimiK2_5, #[serde(rename = "kimi-k2.6")] KimiK2_6, #[serde(rename = "kimi-k2.7-code")] KimiK2_7Code, + #[serde(rename = "kimi-k3")] + KimiK3, #[serde(rename = "minimax-m2.7")] MiniMaxM2_7, #[serde(rename = "minimax-m3")] @@ -163,10 +174,6 @@ pub enum Model { MimoV2_5Pro, #[serde(rename = "mimo-v2.5")] MimoV2_5, - #[serde(rename = "big-pickle")] - BigPickle, - #[serde(rename = "nemotron-3-ultra-free")] - Nemotron3UltraFree, #[serde(rename = "qwen3.5-plus")] Qwen3_5Plus, #[serde(rename = "qwen3.6-plus")] @@ -175,6 +182,10 @@ pub enum Model { Qwen3_7Plus, #[serde(rename = "qwen3.7-max")] Qwen3_7Max, + #[serde(rename = "qwen3.8-max")] + Qwen3_8Max, + #[serde(rename = "hy3")] + Hy3, // -- Custom model -- #[serde(rename = "custom")] @@ -203,40 +214,36 @@ impl Model { Self::MiniMaxM2_7 } - pub fn default_free() -> Self { - Self::BigPickle - } - - pub fn default_free_fast() -> Self { - Self::Nemotron3UltraFree - } - pub fn available_subscriptions(&self) -> &'static [OpenCodeSubscription] { match self { // Models available in both Zen and Go Self::Glm5_1 | Self::Glm5_2 + | Self::Grok4_5 | Self::KimiK2_6 | Self::KimiK2_7Code + | Self::KimiK3 | Self::MiniMaxM2_7 | Self::MiniMaxM3 | Self::DeepSeekV4Pro | Self::DeepSeekV4Flash + | Self::Gpt5_6Luna | Self::Qwen3_6Plus => &[OpenCodeSubscription::Zen, OpenCodeSubscription::Go], // Go-only models - Self::MimoV2_5Pro | Self::MimoV2_5 | Self::Qwen3_7Plus | Self::Qwen3_7Max => { - &[OpenCodeSubscription::Go] - } + Self::MimoV2_5Pro + | Self::MimoV2_5 + | Self::Glm5_3 + | Self::Qwen3_7Plus + | Self::Qwen3_7Max + | Self::Qwen3_8Max + | Self::Hy3 => &[OpenCodeSubscription::Go], // Deprecated on Go (per models.dev); still offered on Zen Self::Glm5 | Self::KimiK2_5 | Self::MiniMaxM2_5 | Self::Qwen3_5Plus => { &[OpenCodeSubscription::Zen] } - // Free models - Self::Nemotron3UltraFree | Self::BigPickle => &[OpenCodeSubscription::Free], - // Custom models get their subscription from settings, not from here Self::Custom { .. } => &[], @@ -247,11 +254,11 @@ impl Model { pub fn id(&self) -> &str { match self { + Self::ClaudeOpus5 => "claude-opus-5", Self::ClaudeOpus4_8 => "claude-opus-4-8", Self::ClaudeOpus4_7 => "claude-opus-4-7", Self::ClaudeOpus4_6 => "claude-opus-4-6", Self::ClaudeOpus4_5 => "claude-opus-4-5", - Self::ClaudeOpus4_1 => "claude-opus-4-1", Self::ClaudeSonnet4_6 => "claude-sonnet-4-6", Self::ClaudeSonnet4_5 => "claude-sonnet-4-5", Self::ClaudeSonnet4 => "claude-sonnet-4", @@ -282,7 +289,10 @@ impl Model { Self::Gemini3_1Pro => "gemini-3.1-pro", Self::Gemini3Flash => "gemini-3-flash", + Self::Gemini3_5FlashLite => "gemini-3.5-flash-lite", Self::Gemini3_5Flash => "gemini-3.5-flash", + Self::Gemini3_6Flash => "gemini-3.6-flash", + Self::Gemini3_7Flash => "gemini-3.7-flash", Self::DeepSeekV4Pro => "deepseek-v4-pro", Self::DeepSeekV4Flash => "deepseek-v4-flash", @@ -290,11 +300,15 @@ impl Model { Self::Glm5 => "glm-5", Self::Glm5_1 => "glm-5.1", Self::Glm5_2 => "glm-5.2", + Self::Glm5_3 => "glm-5.3", Self::GrokBuild0_1 => "grok-build-0.1", Self::Grok4_5 => "grok-4.5", + Self::Grok4_6 => "grok-4.6", + Self::MuseSpark1_2 => "muse-spark-1.2", Self::KimiK2_5 => "kimi-k2.5", Self::KimiK2_6 => "kimi-k2.6", Self::KimiK2_7Code => "kimi-k2.7-code", + Self::KimiK3 => "kimi-k3", Self::MiniMaxM2_7 => "minimax-m2.7", Self::MiniMaxM3 => "minimax-m3", Self::MimoV2_5Pro => "mimo-v2.5-pro", @@ -303,8 +317,8 @@ impl Model { Self::Qwen3_6Plus => "qwen3.6-plus", Self::Qwen3_7Plus => "qwen3.7-plus", Self::Qwen3_7Max => "qwen3.7-max", - Self::BigPickle => "big-pickle", - Self::Nemotron3UltraFree => "nemotron-3-ultra-free", + Self::Qwen3_8Max => "qwen3.8-max", + Self::Hy3 => "hy3", Self::Custom { name, .. } => name, } @@ -312,11 +326,11 @@ impl Model { pub fn display_name(&self) -> &str { match self { + Self::ClaudeOpus5 => "Claude Opus 5", Self::ClaudeOpus4_8 => "Claude Opus 4.8", Self::ClaudeOpus4_7 => "Claude Opus 4.7", Self::ClaudeOpus4_6 => "Claude Opus 4.6", Self::ClaudeOpus4_5 => "Claude Opus 4.5", - Self::ClaudeOpus4_1 => "Claude Opus 4.1", Self::ClaudeSonnet4_6 => "Claude Sonnet 4.6", Self::ClaudeSonnet4_5 => "Claude Sonnet 4.5", Self::ClaudeSonnet4 => "Claude Sonnet 4", @@ -347,7 +361,10 @@ impl Model { Self::Gemini3_1Pro => "Gemini 3.1 Pro", Self::Gemini3Flash => "Gemini 3 Flash", + Self::Gemini3_5FlashLite => "Gemini 3.5 Flash Lite", Self::Gemini3_5Flash => "Gemini 3.5 Flash", + Self::Gemini3_6Flash => "Gemini 3.6 Flash", + Self::Gemini3_7Flash => "Gemini 3.7 Flash", Self::DeepSeekV4Pro => "DeepSeek V4 Pro", Self::DeepSeekV4Flash => "DeepSeek V4 Flash", @@ -355,11 +372,15 @@ impl Model { Self::Glm5 => "GLM 5", Self::Glm5_1 => "GLM 5.1", Self::Glm5_2 => "GLM 5.2", + Self::Glm5_3 => "GLM 5.3", Self::GrokBuild0_1 => "Grok Build 0.1", Self::Grok4_5 => "Grok 4.5", + Self::Grok4_6 => "Grok 4.6", + Self::MuseSpark1_2 => "Muse Spark 1.2", Self::KimiK2_5 => "Kimi K2.5", Self::KimiK2_6 => "Kimi K2.6", Self::KimiK2_7Code => "Kimi K2.7 Code", + Self::KimiK3 => "Kimi K3", Self::MiniMaxM2_7 => "MiniMax M2.7", Self::MiniMaxM3 => "MiniMax M3", Self::MimoV2_5Pro => "MiMo V2.5 Pro", @@ -368,8 +389,8 @@ impl Model { Self::Qwen3_6Plus => "Qwen3.6 Plus", Self::Qwen3_7Plus => "Qwen3.7 Plus", Self::Qwen3_7Max => "Qwen3.7 Max", - Self::BigPickle => "Big Pickle", - Self::Nemotron3UltraFree => "Nemotron 3 Ultra Free", + Self::Qwen3_8Max => "Qwen3.8 Max", + Self::Hy3 => "Hy3", Self::Custom { name, display_name, .. @@ -390,11 +411,11 @@ impl Model { } Self::ClaudeFable5 + | Self::ClaudeOpus5 | Self::ClaudeOpus4_8 | Self::ClaudeOpus4_7 | Self::ClaudeOpus4_6 | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_1 | Self::ClaudeSonnet5 | Self::ClaudeSonnet4_6 | Self::ClaudeSonnet4_5 @@ -422,26 +443,35 @@ impl Model { | Self::Gpt5Codex | Self::Gpt5Nano => ApiProtocol::OpenAiResponses, - Self::Gemini3_1Pro | Self::Gemini3Flash | Self::Gemini3_5Flash => ApiProtocol::Google, + Self::Gemini3_1Pro + | Self::Gemini3Flash + | Self::Gemini3_5FlashLite + | Self::Gemini3_5Flash + | Self::Gemini3_6Flash + | Self::Gemini3_7Flash => ApiProtocol::Google, - Self::Qwen3_7Max | Self::Qwen3_7Plus | Self::Qwen3_6Plus | Self::Qwen3_5Plus => { - ApiProtocol::Anthropic - } + Self::Qwen3_8Max + | Self::Qwen3_7Max + | Self::Qwen3_7Plus + | Self::Qwen3_6Plus + | Self::Qwen3_5Plus => ApiProtocol::Anthropic, Self::Glm5 | Self::Glm5_1 | Self::Glm5_2 + | Self::Glm5_3 | Self::GrokBuild0_1 - | Self::Grok4_5 | Self::KimiK2_5 | Self::KimiK2_6 | Self::KimiK2_7Code + | Self::KimiK3 | Self::MimoV2_5Pro | Self::MimoV2_5 | Self::DeepSeekV4Pro | Self::DeepSeekV4Flash - | Self::BigPickle - | Self::Nemotron3UltraFree => ApiProtocol::OpenAiChat, + | Self::Hy3 => ApiProtocol::OpenAiChat, + + Self::Grok4_6 | Self::Grok4_5 | Self::MuseSpark1_2 => ApiProtocol::OpenAiResponses, Self::Custom { protocol, .. } => *protocol, } @@ -454,16 +484,16 @@ impl Model { | Self::KimiK2_5 | Self::KimiK2_6 | Self::KimiK2_7Code + | Self::KimiK3 | Self::MimoV2_5 | Self::MimoV2_5Pro | Self::Glm5 | Self::Glm5_1 | Self::Glm5_2 + | Self::Glm5_3 | Self::MiniMaxM2_5 | Self::MiniMaxM2_7 - | Self::MiniMaxM3 - | Self::Nemotron3UltraFree - | Self::BigPickle => true, + | Self::MiniMaxM3 => true, Self::Custom { interleaved_reasoning, @@ -477,11 +507,10 @@ impl Model { pub fn max_token_count(&self, subscription: OpenCodeSubscription) -> u64 { match self { // Anthropic models - Self::ClaudeOpus4_8 | Self::ClaudeOpus4_7 => 1_000_000, + Self::ClaudeOpus5 | Self::ClaudeOpus4_8 | Self::ClaudeOpus4_7 => 1_000_000, Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6 => 1_000_000, Self::ClaudeSonnet4_5 => 1_000_000, Self::ClaudeOpus4_5 | Self::ClaudeHaiku4_5 => 200_000, - Self::ClaudeOpus4_1 => 200_000, Self::ClaudeSonnet4 => 1_000_000, Self::ClaudeSonnet5 => 1_000_000, Self::ClaudeFable5 => 1_000_000, @@ -500,9 +529,12 @@ impl Model { Self::Gpt5 | Self::Gpt5Codex | Self::Gpt5Nano => 400_000, // Google models - Self::Gemini3_1Pro => 1_048_576, - Self::Gemini3Flash => 1_048_576, - Self::Gemini3_5Flash => 1_048_576, + Self::Gemini3_1Pro + | Self::Gemini3Flash + | Self::Gemini3_5FlashLite + | Self::Gemini3_5Flash + | Self::Gemini3_6Flash + | Self::Gemini3_7Flash => 1_048_576, // OpenAI-compatible models Self::MiniMaxM2_7 => 204_800, @@ -521,10 +553,12 @@ impl Model { 204_800 } } - Self::Glm5_2 => 1_000_000, + Self::Glm5_3 | Self::Glm5_2 => 1_000_000, Self::KimiK2_6 | Self::KimiK2_5 | Self::KimiK2_7Code => 262_144, + Self::KimiK3 => 1_048_576, Self::GrokBuild0_1 => 256_000, - Self::Grok4_5 => 500_000, + Self::Grok4_6 | Self::Grok4_5 => 500_000, + Self::MuseSpark1_2 => 1_048_576, Self::MimoV2_5Pro => 1_048_576, Self::MimoV2_5 => 1_000_000, Self::Qwen3_5Plus => 262_144, @@ -535,9 +569,8 @@ impl Model { 262_144 } } - Self::Qwen3_7Max | Self::Qwen3_7Plus => 1_000_000, - Self::BigPickle => 200_000, - Self::Nemotron3UltraFree => 1_000_000, + Self::Qwen3_8Max | Self::Qwen3_7Max | Self::Qwen3_7Plus => 1_000_000, + Self::Hy3 => 256_000, Self::DeepSeekV4Pro | Self::DeepSeekV4Flash => 1_000_000, Self::Custom { max_tokens, .. } => *max_tokens, @@ -547,13 +580,14 @@ impl Model { pub fn max_output_tokens(&self, subscription: OpenCodeSubscription) -> Option { match self { // Anthropic models - Self::ClaudeOpus4_8 | Self::ClaudeOpus4_7 | Self::ClaudeOpus4_6 => Some(128_000), + Self::ClaudeOpus5 | Self::ClaudeOpus4_8 | Self::ClaudeOpus4_7 | Self::ClaudeOpus4_6 => { + Some(128_000) + } Self::ClaudeOpus4_5 | Self::ClaudeSonnet4_6 | Self::ClaudeSonnet4_5 | Self::ClaudeHaiku4_5 | Self::ClaudeSonnet4 => Some(64_000), - Self::ClaudeOpus4_1 => Some(32_000), Self::ClaudeSonnet5 => Some(128_000), Self::ClaudeFable5 => Some(128_000), @@ -580,7 +614,12 @@ impl Model { | Self::Gpt5Nano => Some(128_000), // Google models - Self::Gemini3_1Pro | Self::Gemini3Flash | Self::Gemini3_5Flash => Some(65_536), + Self::Gemini3_1Pro + | Self::Gemini3Flash + | Self::Gemini3_5FlashLite + | Self::Gemini3_5Flash + | Self::Gemini3_6Flash + | Self::Gemini3_7Flash => Some(65_536), // OpenAI-compatible models Self::MiniMaxM2_7 => Some(131_072), @@ -605,18 +644,20 @@ impl Model { Some(131_072) } } - Self::Glm5_2 => Some(131_072), - Self::BigPickle => Some(32_000), + Self::Glm5_3 | Self::Glm5_2 => Some(131_072), Self::KimiK2_6 | Self::KimiK2_5 => Some(65_536), Self::KimiK2_7Code => Some(262_144), + Self::KimiK3 => Some(131_072), Self::GrokBuild0_1 => Some(256_000), - Self::Grok4_5 => Some(500_000), + Self::Grok4_6 | Self::Grok4_5 => Some(500_000), + Self::MuseSpark1_2 => Some(131_072), Self::Qwen3_7Max | Self::Qwen3_7Plus | Self::Qwen3_6Plus | Self::Qwen3_5Plus => { Some(65_536) } + Self::Qwen3_8Max => Some(131_072), Self::DeepSeekV4Pro | Self::DeepSeekV4Flash => Some(384_000), - Self::Nemotron3UltraFree => Some(128_000), Self::MimoV2_5Pro | Self::MimoV2_5 => Some(128_000), + Self::Hy3 => Some(64_000), Self::Custom { max_output_tokens, .. @@ -631,11 +672,11 @@ impl Model { pub fn supports_images(&self) -> bool { match self { // Anthropic models support images - Self::ClaudeOpus4_8 + Self::ClaudeOpus5 + | Self::ClaudeOpus4_8 | Self::ClaudeOpus4_7 | Self::ClaudeOpus4_6 | Self::ClaudeOpus4_5 - | Self::ClaudeOpus4_1 | Self::ClaudeSonnet4_6 | Self::ClaudeSonnet4_5 | Self::ClaudeSonnet4 @@ -668,18 +709,27 @@ impl Model { Self::Gpt5_3Spark => false, // Google models support images - Self::Gemini3_1Pro | Self::Gemini3Flash | Self::Gemini3_5Flash => true, + Self::Gemini3_1Pro + | Self::Gemini3Flash + | Self::Gemini3_5FlashLite + | Self::Gemini3_5Flash + | Self::Gemini3_6Flash + | Self::Gemini3_7Flash => true, // OpenAI-compatible models with image support Self::KimiK2_6 + | Self::KimiK3 | Self::KimiK2_7Code | Self::KimiK2_5 | Self::GrokBuild0_1 | Self::Grok4_5 + | Self::Grok4_6 + | Self::MuseSpark1_2 | Self::MimoV2_5 | Self::Qwen3_5Plus | Self::Qwen3_6Plus | Self::Qwen3_7Plus + | Self::Qwen3_8Max | Self::MiniMaxM3 => true, // OpenAI-compatible models without image support @@ -687,13 +737,13 @@ impl Model { | Self::Glm5 | Self::Glm5_1 | Self::Glm5_2 + | Self::Glm5_3 | Self::MiniMaxM2_7 | Self::MimoV2_5Pro | Self::DeepSeekV4Pro | Self::DeepSeekV4Flash | Self::Qwen3_7Max - | Self::BigPickle - | Self::Nemotron3UltraFree => false, + | Self::Hy3 => false, Self::Custom { protocol, .. } => matches!( protocol, @@ -709,6 +759,7 @@ impl Model { match self { // Anthropic models Self::ClaudeFable5 + | Self::ClaudeOpus5 | Self::ClaudeOpus4_8 | Self::ClaudeOpus4_7 | Self::ClaudeSonnet5 => Some(vec![ @@ -789,14 +840,17 @@ impl Model { ]), // Google models - Self::Gemini3Flash | Self::Gemini3_5Flash => Some(vec![ + Self::Gemini3Flash + | Self::Gemini3_5FlashLite + | Self::Gemini3_5Flash + | Self::Gemini3_6Flash => Some(vec![ ReasoningEffort::Minimal, ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High, ]), - Self::Gemini3_1Pro => Some(vec![ + Self::Gemini3_7Flash | Self::Gemini3_1Pro => Some(vec![ ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High, @@ -809,16 +863,12 @@ impl Model { ReasoningEffort::Max, ]), + // Moonshot AI models + Self::KimiK3 => Some(vec![ReasoningEffort::Max]), + // MiniMax models Self::MiniMaxM3 => Some(vec![ReasoningEffort::None]), - // NVIDIA models - Self::Nemotron3UltraFree => Some(vec![ - ReasoningEffort::Low, - ReasoningEffort::Medium, - ReasoningEffort::High, - ]), - // Xiaomi MiMo models Self::MimoV2_5Pro | Self::MimoV2_5 => Some(vec![ ReasoningEffort::Low, @@ -829,13 +879,42 @@ impl Model { // Z AI models Self::Glm5_2 => Some(vec![ReasoningEffort::High, ReasoningEffort::Max]), + Self::Glm5_3 => Some(vec![ + ReasoningEffort::Low, + ReasoningEffort::High, + ReasoningEffort::Max, + ]), + + // Tencent models + Self::Hy3 => Some(vec![ + ReasoningEffort::None, + ReasoningEffort::Low, + ReasoningEffort::High, + ]), + // SpaceXAI models + Self::Grok4_6 => Some(vec![ + ReasoningEffort::Low, + ReasoningEffort::Medium, + ReasoningEffort::High, + ReasoningEffort::XHigh, + ]), + Self::Grok4_5 => Some(vec![ ReasoningEffort::Low, ReasoningEffort::Medium, ReasoningEffort::High, ]), + // Meta AI models + Self::MuseSpark1_2 => Some(vec![ + ReasoningEffort::Minimal, + ReasoningEffort::Low, + ReasoningEffort::Medium, + ReasoningEffort::High, + ReasoningEffort::XHigh, + ]), + Self::Custom { reasoning_effort_levels, .. diff --git a/crates/settings_content/src/language_model.rs b/crates/settings_content/src/language_model.rs index 735c3d20e1609d..06239c76c2b386 100644 --- a/crates/settings_content/src/language_model.rs +++ b/crates/settings_content/src/language_model.rs @@ -245,8 +245,6 @@ pub struct OpenCodeSettingsContent { pub show_zen_models: Option, /// Whether to show OpenCode Go models. Defaults to true. pub show_go_models: Option, - /// Whether to show OpenCode Free models. Defaults to true. - pub show_free_models: Option, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)] @@ -266,7 +264,6 @@ pub enum OpenCodeApiProtocol { pub enum OpenCodeModelSubscription { Zen, Go, - Free, } #[with_fallible_options] @@ -278,7 +275,7 @@ pub struct OpenCodeAvailableModel { pub max_output_tokens: Option, /// The API protocol to use for this model: "anthropic", "openai_responses", "openai_chat", or "google". Defaults to "openai_chat". pub protocol: Option, - /// The subscription for this model: "zen", "go", or "free". Defaults to Zen. + /// The subscription for this model: "zen" or "go". Defaults to Zen. pub subscription: Option, /// Custom Model API URL to use for this model. pub custom_model_api_url: Option, diff --git a/docs/src/ai/use-api-access.md b/docs/src/ai/use-api-access.md index 7af0c0e68a3948..2064fce9c1d754 100644 --- a/docs/src/ai/use-api-access.md +++ b/docs/src/ai/use-api-access.md @@ -349,7 +349,10 @@ Use OpenCode API access when you have an OpenCode API key. OpenCode Zen and Go a Zed does not sign in to OpenCode with OAuth or detect your OpenCode subscription; it uses an OpenCode API key saved in the system keychain or `OPENCODE_API_KEY`. 1. Visit [OpenCode Console](https://opencode.ai/auth) and create an account. -2. Free models are available without payment. To use Zen or Go models, make sure you have enough credits or an active subscription. +2. To use Zen or Go models, make sure you have enough credits or an active + subscription. OpenCode Free models are not available when using OpenCode as a + provider in Zed's Agent. You can use them in Zed by running OpenCode as an + [external agent through ACP](https://zed.dev/acp/agent/opencode). 3. Generate an API key from the API Keys section in the OpenCode Console. 4. Open Agent Settings with {#action agent::OpenSettings} and go to the OpenCode section. 5. Enter your OpenCode API key. @@ -362,19 +365,16 @@ By default, models from all OpenCode subscription types are shown. You can hide { "language_models": { "opencode": { - "show_zen_models": true, - "show_go_models": false, - "show_free_models": false + "show_zen_models": false, + "show_go_models": true } } } ``` -**Note:** Zed only bundles configuration for long-term OpenCode Free models. Free models that are available for a limited time are not included in Zed. To use those models, add a custom OpenCode model with configuration from [the OpenCode website](https://opencode.ai/docs/zen#pricing) and [models.dev](https://github.com/anomalyco/models.dev/tree/dev/providers/opencode/models). - #### Custom OpenCode Models {#opencode-custom-models} -The Zed Agent comes preconfigured with OpenCode models. Add custom OpenCode models when you need newer models, limited-time Free models, or models with custom endpoints. +The Zed Agent comes preconfigured with OpenCode models. Add custom OpenCode models when you need newer models or models with custom endpoints. Add custom models in your settings file: @@ -409,7 +409,7 @@ The available configuration options for custom OpenCode models are: - `protocol` (optional, default `"openai_chat"`): model API protocol, one of `"anthropic"`, `"openai_responses"`, `"openai_chat"`, or `"google"` - `reasoning_effort_levels` (optional): list of supported reasoning effort levels, such as `["none", "low", "medium", "high", "xhigh", "max"]`. The last value in the list is used as the default - `interleaved_reasoning` (optional, default `false`): whether thinking tokens are sent as a dedicated `reasoning_content` field. Applies only when using the `openai_chat` protocol -- `subscription` (optional): `"zen"`, `"go"`, or `"free"`; defaults to `"zen"` +- `subscription` (optional): `"zen"` or `"go"`; defaults to `"zen"` - `custom_model_api_url` (optional): custom API base URL to use instead of the default OpenCode API Custom OpenCode models are listed in the model dropdown in the Agent Panel.