Closes https://github.com/zed-industries/zed/issues/62559 Related discussion: https://github.com/zed-industries/zed/discussions/61160 # Objective Adding newly-released OpenCode models. Removing OpenCode Free models completely. ## Solution > [!TIP] > This pull request is **best reviewed commit-by-commit**! **OpenCode Go**: - added **Kimi K3** as per [[1]](https://github.com/anomalyco/models.dev/blob/89183a9646cf2fa30300f7203a5b4f2ca69d1374/providers/opencode-go/models/kimi-k3.toml) and [[2]](https://github.com/anomalyco/models.dev/blob/dev/models/moonshotai/kimi-k3.toml). Currently, the only supported reasoning level available is `Max` which was validated both with Models.dev data and OpenCode CLI. - added **Grok 4.5** as per [[1]](https://github.com/anomalyco/models.dev/blob/89183a9646cf2fa30300f7203a5b4f2ca69d1374/providers/opencode-go/models/grok-4.5.toml) and [[2]](https://github.com/anomalyco/models.dev/blob/89183a9646cf2fa30300f7203a5b4f2ca69d1374/models/xai/grok-4.5.toml) - added **Tencent Hy3** as per [[1]](https://github.com/anomalyco/models.dev/commit/b013d94872bb5993fad19ad35fadf74cb029516e) and [[2]](https://github.com/anomalyco/models.dev/blob/f63b5ce78dd78869faa0612353b1055f6608dc97/models/tencent/hy3.toml) - added **GPT 5.6 Luna** as per [[1]](https://github.com/anomalyco/opencode/pull/39812) and [[2]](https://github.com/anomalyco/models.dev/blob/dev/providers/opencode-go/models/gpt-5.6-luna.toml) - added **Qwen 3.8 Max** as per [[1]](https://github.com/anomalyco/models.dev/commit/403a7bdd43ac7daeadc8bb755eccabf66a0afb9d) and [[2]](https://github.com/anomalyco/opencode/commit/e9e747245681127c9f3e300aa8c46f2554fdb294) - added **GLM 5.3** as per [[1]](https://github.com/anomalyco/models.dev/blob/3876740bf4f0290e014bc85340e1dba34f0e99a7/models/zhipuai/glm-5.3.toml) and [[2]](https://github.com/anomalyco/models.dev/commit/94a1629610b579fd80f7c488f5e4e8d78c8b6883) and [[3]](https://github.com/anomalyco/opencode/pull/42518) **OpenCode Zen**: - added **Gemini 3.5 Flash Lite** as per [[1]](https://github.com/anomalyco/models.dev/blob/f63b5ce78dd78869faa0612353b1055f6608dc97/providers/opencode/models/gemini-3.5-flash-lite.toml) and [[2]](https://github.com/anomalyco/models.dev/blob/f63b5ce78dd78869faa0612353b1055f6608dc97/models/google/gemini-3.5-flash-lite.toml) - added **Gemini 3.6 Flash** as per [[1]](https://github.com/anomalyco/models.dev/blob/f63b5ce78dd78869faa0612353b1055f6608dc97/providers/opencode/models/gemini-3.6-flash.toml) and [[2]](https://github.com/anomalyco/models.dev/blob/f63b5ce78dd78869faa0612353b1055f6608dc97/models/google/gemini-3.6-flash.toml) - added **Gemini 3.7 Flash** as per [[1]](https://github.com/anomalyco/models.dev/pull/4632) and [[2]](https://github.com/anomalyco/models.dev/commit/b1810e30d7abb11af1092b51aa28cbafc2c440b8) and [[3]](https://github.com/anomalyco/opencode/pull/42390) and [[4]](https://github.com/anomalyco/opencode/pull/42393) - added **Claude Opus 5** as per [[1]](https://github.com/anomalyco/models.dev/commit/e3ae24cdd7fb524d73e1569ed1713991c5ba688c) and [[2]](https://github.com/anomalyco/models.dev/commit/342b5572a06735d0efa8c3c419589051199459d8) - added **Kimi K3** as per [[1]](https://github.com/anomalyco/opencode/commit/a9bebd36530dbab28c4644eb7b35b2b1460b8b90) and [[2]](https://github.com/anomalyco/models.dev/commit/38ccccc20d7d827f99d791d07cc4cedb8b4eec24) - added **Grok 4.6** as per [[1]](https://github.com/anomalyco/models.dev/commit/74789f5a02746cf6c40b75c342432a9d525c28b9) and [[2]](https://github.com/anomalyco/opencode/commit/d92d1e654bd1aa8ccb972b3059825314c1633eb8) and [[3]](https://github.com/anomalyco/models.dev/pull/4575) - added **Muse Spark 1.2** as per [[1]](https://github.com/anomalyco/models.dev/commit/fa03dca90bad225a09263ad6ad227c7f47d0172d) and [[2]](https://github.com/anomalyco/models.dev/blob/3876740bf4f0290e014bc85340e1dba34f0e99a7/models/meta/muse-spark-1.2.toml) and [[3]](https://github.com/anomalyco/opencode/pull/42508) - removed **Claude Opus 4.1** as per [[1]](https://github.com/anomalyco/models.dev/commit/6951484e985fe55646a741ccd3ca1d4b15008e3f) **OpenCode Free**: removed all the models and the whole concept of "OpenCode Free" from Zed. As confirmed [by an Anomaly employee on the OpenCode Discord](https://discord.com/channels/1391832426048651334/1394667004979445931/1537530485356363899), free models are now OpenCode-only since they got abused waaaaay too much by people. Testing shows that even with an active OpenCode Go subscription configured, I can't use Free models in Zed — both Big Pickle and DeepSeek V4 Flash Free failed to reply to a _"hello"_ message and instead returned a rate-limit error. A full removal of OpenCode Free from Zed was implemented in https://github.com/zed-industries/zed/pull/61199/changes/49acbf7c92414c14c453113eb9b886f9bedff7cb as there was no point in keeping a _"Show free models"_ toggle that would confuse users. Users that had `show_free_models` configures in Zed settings will get an `Property show_free_models is not allowed.` notice. Users that had any Custom OpenCode models with `"subscription": "free"` configured will get an `Value is not accepted. Valid values: "zen", "go".` notice. Neither are blocking errors. ## Testing ✅ Kimi K3 on OpenCode Go - happily confirmed Kimi K3 works by running a simple "_rename this variable for me. add a function. delete the function_" test. ✅ Grok 4.5 on OpenCode Go - bravely resisted the continuous and relentless waves of disgust and confirmed Grok 4.5 works by running a simple "_rename this variable for me. add a function. delete the function_" test. I was a bit surprised this worked as I was located in an EU country while testing this. ✅ Hy3 on OpenCode Go - happily confirmed Hy3 works by running a simple "_rename this variable for me. add a function. delete the function_" test. ✅ GPT 5.6 Luna on OpeCode Go - confirmed GPT 5.6 Luna works on OpenCode Go by running a simple "_rename this variable for me. add a function. delete the function_" test. ✅ Qwen 3.8 Max on OpeCode Go - confirmed Qwen 3.8 Max works on OpenCode Go by running a simple "_rename this variable for me. add a function. delete the function_" test. ✅ GLM 5.3 on OpeCode Go - confirmed GLM 5.3 works on OpenCode Go by running a simple "_rename this variable for me. add a function. delete the function_" test. 🤷 I did not test the new OpenCode Zen models (Claude Opus 5, Gemini 3.5 Flash Lite, Gemini 3.6 Flash, Kimi K3, Grok 4.6, Gemini 3.7 Flash, and Muse Spark 1.2) as I don't have a Zen subscription and I am stubbornly refusing to get one. ✅ Confirmed removal of OpenCode Free does not impact the rest of the OpenCode. Confirmed that any Free-related settings generate notices and not errors. Confirmed the OpenCode tab in Setting looks good. ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable ## Showcase <details> <summary>Screenshots of the OpenCode Free deprecation warnings</summary> **Notice shown in the corner of Zed**: <img width="345" height="90" alt="Notice banner shown in Zed" src="https://github.com/user-attachments/assets/3e65ba96-582c-424e-9335-1b43d6c632a8" /> **Notice shown in Settings -> LLM Providers -> OpenCode**: <img width="421" height="323" alt="Settings screen showing unexpected values" src="https://github.com/user-attachments/assets/a5eb6005-8576-4311-8b23-9c5baf314d8d" /> **Notice shown in `settings.json`**: <img width="569" height="231" alt="Notices shown in settings.json" src="https://github.com/user-attachments/assets/475375a1-268c-4420-8ef7-a896548e4498" /> </details> --- Release Notes: - Removed OpenCode Free models from Zed's built-in OpenCode provider because they are only available through OpenCode surfaces, such as its external agent through ACP. - Added Kimi K3, Grok 4.5, Hy3, GPT 5.6 Luna, Qwen 3.8 Max, and GLM 5.3 to OpenCode Go. - Added Claude Opus 5, Gemini 3.5 Flash Lite, Gemini 3.6 Flash, Gemini 3.7 Flash, Kimi K3, Grok 4.6, and Muse Spark 1.2 to OpenCode Zen. - Removed the deprecated Claude Opus 4.1 model from OpenCode Zen. ---- > [!TIP] > This pull request is **best reviewed commit-by-commit**! --------- Co-authored-by: dino <dinojoaocosta@gmail.com>
214 lines
9.8 KiB
Rust
214 lines
9.8 KiB
Rust
use std::sync::Arc;
|
|
|
|
use collections::HashMap;
|
|
use settings::RegisterSetting;
|
|
|
|
use crate::provider::{
|
|
anthropic, anthropic::AnthropicSettings, anthropic_compatible::AnthropicCompatibleSettings,
|
|
bedrock, bedrock::AmazonBedrockSettings, cloud::ZedDotDevSettings, deepseek::DeepSeekSettings,
|
|
google::GoogleSettings, llama_cpp::LlamaCppSettings, lmstudio::LmStudioSettings, mistral,
|
|
mistral::MistralSettings, ollama::OllamaSettings, open_ai::OpenAiSettings,
|
|
open_ai_compatible::OpenAiCompatibleSettings, open_router, open_router::OpenRouterSettings,
|
|
opencode, opencode::OpenCodeSettings, resolve_custom_headers,
|
|
vercel_ai_gateway::VercelAiGatewaySettings, x_ai::XAiSettings,
|
|
};
|
|
|
|
#[derive(Debug, RegisterSetting)]
|
|
pub struct AllLanguageModelSettings {
|
|
pub anthropic: AnthropicSettings,
|
|
pub anthropic_compatible: HashMap<Arc<str>, AnthropicCompatibleSettings>,
|
|
pub bedrock: AmazonBedrockSettings,
|
|
pub deepseek: DeepSeekSettings,
|
|
pub google: GoogleSettings,
|
|
pub llama_cpp: LlamaCppSettings,
|
|
pub lmstudio: LmStudioSettings,
|
|
pub mistral: MistralSettings,
|
|
pub ollama: OllamaSettings,
|
|
pub opencode: OpenCodeSettings,
|
|
pub open_router: OpenRouterSettings,
|
|
pub openai: OpenAiSettings,
|
|
pub openai_compatible: HashMap<Arc<str>, OpenAiCompatibleSettings>,
|
|
pub vercel_ai_gateway: VercelAiGatewaySettings,
|
|
pub x_ai: XAiSettings,
|
|
pub zed_dot_dev: ZedDotDevSettings,
|
|
}
|
|
|
|
fn custom_headers_from(
|
|
provider_name: &str,
|
|
raw: Option<HashMap<String, String>>,
|
|
reserved: &[&str],
|
|
) -> http_client::CustomHeaders {
|
|
raw.as_ref()
|
|
.filter(|map| !map.is_empty())
|
|
.map(|map| resolve_custom_headers(provider_name, map, reserved))
|
|
.unwrap_or_default()
|
|
}
|
|
|
|
impl settings::Settings for AllLanguageModelSettings {
|
|
const PRESERVED_KEYS: Option<&'static [&'static str]> = Some(&["version"]);
|
|
|
|
fn from_settings(content: &settings::SettingsContent) -> Self {
|
|
let language_models = content.language_models.clone().unwrap();
|
|
let anthropic = language_models.anthropic.unwrap();
|
|
let anthropic_compatible = language_models.anthropic_compatible.unwrap();
|
|
let bedrock = language_models.bedrock.unwrap();
|
|
let deepseek = language_models.deepseek.unwrap();
|
|
let google = language_models.google.unwrap();
|
|
let llama_cpp = language_models.llama_cpp.unwrap();
|
|
let lmstudio = language_models.lmstudio.unwrap();
|
|
let mistral = language_models.mistral.unwrap();
|
|
let ollama = language_models.ollama.unwrap();
|
|
let opencode = language_models.opencode.unwrap();
|
|
let open_router = language_models.open_router.unwrap();
|
|
let openai = language_models.openai.unwrap();
|
|
let openai_compatible = language_models.openai_compatible.unwrap();
|
|
let vercel_ai_gateway = language_models.vercel_ai_gateway.unwrap();
|
|
let x_ai = language_models.x_ai.unwrap();
|
|
let zed_dot_dev = language_models.zed_dot_dev.unwrap();
|
|
Self {
|
|
anthropic: AnthropicSettings {
|
|
api_url: anthropic.api_url.unwrap(),
|
|
available_models: anthropic.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from(
|
|
"Anthropic",
|
|
anthropic.custom_headers,
|
|
anthropic::RESERVED_HEADER_NAMES,
|
|
),
|
|
},
|
|
anthropic_compatible: anthropic_compatible
|
|
.into_iter()
|
|
.map(|(key, value)| {
|
|
let provider_label = format!("Anthropic Compatible ({key})");
|
|
(
|
|
key,
|
|
AnthropicCompatibleSettings {
|
|
api_url: value.api_url,
|
|
available_models: value.available_models,
|
|
custom_headers: custom_headers_from(
|
|
&provider_label,
|
|
value.custom_headers,
|
|
anthropic::RESERVED_HEADER_NAMES,
|
|
),
|
|
},
|
|
)
|
|
})
|
|
.collect(),
|
|
bedrock: AmazonBedrockSettings {
|
|
available_models: bedrock.available_models.unwrap_or_default(),
|
|
mantle_available_models: bedrock.mantle_available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from(
|
|
"Amazon Bedrock",
|
|
bedrock.custom_headers,
|
|
bedrock::RESERVED_HEADER_NAMES,
|
|
),
|
|
region: bedrock.region,
|
|
endpoint: bedrock.endpoint_url, // todo(should be api_url)
|
|
profile_name: bedrock.profile,
|
|
role_arn: None, // todo(was never a setting for this...)
|
|
authentication_method: bedrock.authentication_method.map(Into::into),
|
|
allow_global: bedrock.allow_global,
|
|
guardrail_identifier: bedrock.guardrail_identifier,
|
|
guardrail_version: bedrock.guardrail_version,
|
|
},
|
|
deepseek: DeepSeekSettings {
|
|
api_url: deepseek.api_url.unwrap(),
|
|
available_models: deepseek.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from("DeepSeek", deepseek.custom_headers, &[]),
|
|
},
|
|
google: GoogleSettings {
|
|
api_url: google.api_url.unwrap(),
|
|
available_models: google.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from("Google AI", google.custom_headers, &[]),
|
|
},
|
|
llama_cpp: LlamaCppSettings {
|
|
api_url: llama_cpp.api_url.unwrap(),
|
|
auto_discover: llama_cpp.auto_discover.unwrap_or(true),
|
|
available_models: llama_cpp.available_models.unwrap_or_default(),
|
|
context_window: llama_cpp.context_window,
|
|
custom_headers: custom_headers_from("llama.cpp", llama_cpp.custom_headers, &[]),
|
|
},
|
|
lmstudio: LmStudioSettings {
|
|
api_url: lmstudio.api_url.unwrap(),
|
|
available_models: lmstudio.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from("LM Studio", lmstudio.custom_headers, &[]),
|
|
},
|
|
mistral: MistralSettings {
|
|
api_url: mistral.api_url.unwrap(),
|
|
available_models: mistral.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from(
|
|
"Mistral",
|
|
mistral.custom_headers,
|
|
mistral::RESERVED_HEADER_NAMES,
|
|
),
|
|
},
|
|
ollama: OllamaSettings {
|
|
api_url: ollama.api_url.unwrap(),
|
|
auto_discover: ollama.auto_discover.unwrap_or(true),
|
|
available_models: ollama.available_models.unwrap_or_default(),
|
|
context_window: ollama.context_window,
|
|
custom_headers: custom_headers_from("Ollama", ollama.custom_headers, &[]),
|
|
},
|
|
opencode: OpenCodeSettings {
|
|
api_url: opencode.api_url.unwrap(),
|
|
available_models: opencode.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from(
|
|
"OpenCode",
|
|
opencode.custom_headers,
|
|
opencode::RESERVED_HEADER_NAMES,
|
|
),
|
|
show_zen_models: opencode.show_zen_models.unwrap_or(true),
|
|
show_go_models: opencode.show_go_models.unwrap_or(true),
|
|
},
|
|
open_router: OpenRouterSettings {
|
|
api_url: open_router.api_url.unwrap(),
|
|
available_models: open_router.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from(
|
|
"OpenRouter",
|
|
open_router.custom_headers,
|
|
open_router::RESERVED_HEADER_NAMES,
|
|
),
|
|
},
|
|
openai: OpenAiSettings {
|
|
api_url: openai.api_url.unwrap(),
|
|
available_models: openai.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from("OpenAI", openai.custom_headers, &[]),
|
|
},
|
|
openai_compatible: openai_compatible
|
|
.into_iter()
|
|
.map(|(key, value)| {
|
|
let provider_label = format!("OpenAI Compatible ({key})");
|
|
(
|
|
key,
|
|
OpenAiCompatibleSettings {
|
|
api_url: value.api_url,
|
|
available_models: value.available_models,
|
|
custom_headers: custom_headers_from(
|
|
&provider_label,
|
|
value.custom_headers,
|
|
&[],
|
|
),
|
|
},
|
|
)
|
|
})
|
|
.collect(),
|
|
vercel_ai_gateway: VercelAiGatewaySettings {
|
|
api_url: vercel_ai_gateway.api_url.unwrap(),
|
|
available_models: vercel_ai_gateway.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from(
|
|
"Vercel AI Gateway",
|
|
vercel_ai_gateway.custom_headers,
|
|
&[],
|
|
),
|
|
},
|
|
x_ai: XAiSettings {
|
|
api_url: x_ai.api_url.unwrap(),
|
|
available_models: x_ai.available_models.unwrap_or_default(),
|
|
custom_headers: custom_headers_from("xAI", x_ai.custom_headers, &[]),
|
|
},
|
|
zed_dot_dev: ZedDotDevSettings {
|
|
available_models: zed_dot_dev.available_models.unwrap_or_default(),
|
|
},
|
|
}
|
|
}
|
|
}
|