opencode: Model updates + fixes (#60526)
**TL;DR**: model updates + reasoning levels + fixes discovered when working on https://github.com/zed-industries/zed/pull/60373 # Objective Since the model auto-discovery PR was [cancelled](https://github.com/zed-industries/zed/pull/60373#issuecomment-4886521448), here is a manual model list update! I also copied the stand-alone bugfixes/enhancements from that PR. ## Solution A lot of manual work 😅 **OpenCode Zen**: - added Fable 5 and Sonnet 5 - added models that were previously only available on OpenCode Go: GLM 5.2, Kimi K2.7 Code, and Minimax M3 - added reasoning levels for all models. I started from the data on [`Models.dev`](https://models.dev) (the `/api.json` raw data), and then I matched that with what is shown in the OpenCode CLI and what I know to be true **OpenCode Go**: - added reasoning levels for GLM 5.2 **OpenCode in general**: - added `protocol` validation for the settings, by moving from a random `String` to an `enum`, for both nicer error messages (random strings or typos will get an error instead of using `openai_chat` by default) and to avoid issues like [folks saying non-existent protocols are a thing](https://github.com/zed-industries/zed/issues/56869#issuecomment-4550154554) - enabled parallel tool calls by default. As per [OpenCode developer on Discord](https://discord.com/channels/1391832426048651334/1471233160993050918/1472020924881702912), _"almost all models worth using support parallel tool calling natively"_. Manual tests confirmed all OpenCode Go models support this correctly (and was enabled by default on the OpenCode side for all but 1 model). I initially wanted to skip this from the release notes, but I added it so folks are aware of it in case any issues are caused by this being enabled for all models - allegedly fixed Google thinking since reasoning levels / thinking effort levels were added for Google models and an auto-checker LLM highlighted that was not properly configured - added support for the new-ish `supports_disabling_thinking` so thinking-only models don't get a no-impact toggle to disable thinking I have no idea if any of the Free models will disappear in 2 days or not, so I did not update those 🤷 (as per decision in https://github.com/zed-industries/zed/issues/56869#issuecomment-4466637648) ## Testing The Zen and Google changes were not tested as I don't have a Zen subscription and I stubbornly refuse to get one. The Free&Go changes were tested by running a "_rename this variable for me. add a function. delete the function_" test with a few different models. ## 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 --- Release Notes: - Agent: OpenCode settings now validate `protocol` values - Agent: OpenCode only shows the "Disable thinking" toggle if thinking can indeed be disabled/enabled - Agent: OpenCode models now enable parallel tool calls by default - Agent: Updated OpenCode Zen models (added Fable 5, Sonnet 5, GLM 5.2, Kimi K2.7 Code, and Minimax M3) - Agent: Added OpenCode Go GLM 5.2 reasoning effort levels - Agent: Added reasoning effort levels for all OpenCode Zen models - Agent: Fixed thinking for OpenCode Zen Google models
This commit is contained in:
1 parent
2b47bfd6b2
commit
114307768e
4 files changed
+191
-49
No files matched your search
+152
-32
@@ -77,6 +77,10 @@ pub enum Model {
|
||||
ClaudeSonnet4,
|
||||
#[serde(rename = "claude-haiku-4-5")]
|
||||
ClaudeHaiku4_5,
|
||||
#[serde(rename = "claude-sonnet-5")]
|
||||
ClaudeSonnet5,
|
||||
#[serde(rename = "claude-fable-5")]
|
||||
ClaudeFable5,
|
||||
|
||||
// -- OpenAI Responses API models --
|
||||
#[serde(rename = "gpt-5.5")]
|
||||
@@ -203,23 +207,24 @@ impl Model {
|
||||
match self {
|
||||
// Models available in both Zen and Go
|
||||
Self::Glm5_1
|
||||
| Self::Glm5_2
|
||||
| Self::KimiK2_6
|
||||
| Self::KimiK2_7Code
|
||||
| Self::MiniMaxM2_7
|
||||
| Self::MiniMaxM3
|
||||
| Self::DeepSeekV4Pro
|
||||
| Self::DeepSeekV4Flash
|
||||
| Self::Qwen3_6Plus => &[OpenCodeSubscription::Zen, OpenCodeSubscription::Go],
|
||||
|
||||
// Go-only models
|
||||
Self::MimoV2_5Pro
|
||||
| Self::MimoV2_5
|
||||
| Self::Qwen3_7Plus
|
||||
| Self::Qwen3_7Max
|
||||
| Self::KimiK2_7Code
|
||||
| Self::Glm5_2
|
||||
| Self::MiniMaxM3 => &[OpenCodeSubscription::Go],
|
||||
Self::MimoV2_5Pro | Self::MimoV2_5 | Self::Qwen3_7Plus | Self::Qwen3_7Max => {
|
||||
&[OpenCodeSubscription::Go]
|
||||
}
|
||||
|
||||
// Deprecated on Go (per models.dev); still offered on Zen
|
||||
Self::Glm5 | Self::KimiK2_5 | Self::MiniMaxM2_5 => &[OpenCodeSubscription::Zen],
|
||||
Self::Glm5 | Self::KimiK2_5 | Self::MiniMaxM2_5 | Self::Qwen3_5Plus => {
|
||||
&[OpenCodeSubscription::Zen]
|
||||
}
|
||||
|
||||
// Free models
|
||||
Self::Nemotron3UltraFree | Self::BigPickle => &[OpenCodeSubscription::Free],
|
||||
@@ -243,6 +248,8 @@ impl Model {
|
||||
Self::ClaudeSonnet4_5 => "claude-sonnet-4-5",
|
||||
Self::ClaudeSonnet4 => "claude-sonnet-4",
|
||||
Self::ClaudeHaiku4_5 => "claude-haiku-4-5",
|
||||
Self::ClaudeSonnet5 => "claude-sonnet-5",
|
||||
Self::ClaudeFable5 => "claude-fable-5",
|
||||
|
||||
Self::Gpt5_5 => "gpt-5.5",
|
||||
Self::Gpt5_5Pro => "gpt-5.5-pro",
|
||||
@@ -302,6 +309,8 @@ impl Model {
|
||||
Self::ClaudeSonnet4_5 => "Claude Sonnet 4.5",
|
||||
Self::ClaudeSonnet4 => "Claude Sonnet 4",
|
||||
Self::ClaudeHaiku4_5 => "Claude Haiku 4.5",
|
||||
Self::ClaudeSonnet5 => "Claude Sonnet 5",
|
||||
Self::ClaudeFable5 => "Claude Fable 5",
|
||||
|
||||
Self::Gpt5_5 => "GPT 5.5",
|
||||
Self::Gpt5_5Pro => "GPT 5.5 Pro",
|
||||
@@ -356,7 +365,7 @@ impl Model {
|
||||
match self {
|
||||
// Models offered by OpenCode have the same configuration across subscriptions
|
||||
// with one outlier: non-free MiniMax models
|
||||
Self::MiniMaxM2_7 | Self::MiniMaxM2_5 => {
|
||||
Self::MiniMaxM3 | Self::MiniMaxM2_7 | Self::MiniMaxM2_5 => {
|
||||
if subscription == OpenCodeSubscription::Zen {
|
||||
ApiProtocol::OpenAiChat
|
||||
} else {
|
||||
@@ -364,11 +373,13 @@ impl Model {
|
||||
}
|
||||
}
|
||||
|
||||
Self::ClaudeOpus4_8
|
||||
Self::ClaudeFable5
|
||||
| Self::ClaudeOpus4_8
|
||||
| Self::ClaudeOpus4_7
|
||||
| Self::ClaudeOpus4_6
|
||||
| Self::ClaudeOpus4_5
|
||||
| Self::ClaudeOpus4_1
|
||||
| Self::ClaudeSonnet5
|
||||
| Self::ClaudeSonnet4_6
|
||||
| Self::ClaudeSonnet4_5
|
||||
| Self::ClaudeSonnet4
|
||||
@@ -394,9 +405,9 @@ impl Model {
|
||||
|
||||
Self::Gemini3_1Pro | Self::Gemini3Flash | Self::Gemini3_5Flash => ApiProtocol::Google,
|
||||
|
||||
Self::Qwen3_7Max | Self::Qwen3_7Plus => ApiProtocol::Anthropic,
|
||||
|
||||
Self::MiniMaxM3 => ApiProtocol::Anthropic,
|
||||
Self::Qwen3_7Max | Self::Qwen3_7Plus | Self::Qwen3_6Plus | Self::Qwen3_5Plus => {
|
||||
ApiProtocol::Anthropic
|
||||
}
|
||||
|
||||
Self::Glm5
|
||||
| Self::Glm5_1
|
||||
@@ -407,8 +418,6 @@ impl Model {
|
||||
| Self::KimiK2_7Code
|
||||
| Self::MimoV2_5Pro
|
||||
| Self::MimoV2_5
|
||||
| Self::Qwen3_5Plus
|
||||
| Self::Qwen3_6Plus
|
||||
| Self::DeepSeekV4Pro
|
||||
| Self::DeepSeekV4Flash
|
||||
| Self::BigPickle
|
||||
@@ -432,6 +441,7 @@ impl Model {
|
||||
| Self::Glm5_2
|
||||
| Self::MiniMaxM2_5
|
||||
| Self::MiniMaxM2_7
|
||||
| Self::MiniMaxM3
|
||||
| Self::Nemotron3UltraFree
|
||||
| Self::BigPickle => true,
|
||||
|
||||
@@ -453,6 +463,8 @@ impl Model {
|
||||
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,
|
||||
|
||||
// OpenAI models
|
||||
Self::Gpt5_5 | Self::Gpt5_5Pro => 1_050_000,
|
||||
@@ -473,7 +485,13 @@ impl Model {
|
||||
|
||||
// OpenAI-compatible models
|
||||
Self::MiniMaxM2_7 => 204_800,
|
||||
Self::MiniMaxM3 => 512_000,
|
||||
Self::MiniMaxM3 => {
|
||||
if subscription == OpenCodeSubscription::Go {
|
||||
1_000_000
|
||||
} else {
|
||||
512_000
|
||||
}
|
||||
}
|
||||
Self::MiniMaxM2_5 => 204_800,
|
||||
Self::Glm5 | Self::Glm5_1 => {
|
||||
if subscription == OpenCodeSubscription::Go {
|
||||
@@ -514,6 +532,8 @@ impl Model {
|
||||
| Self::ClaudeHaiku4_5
|
||||
| Self::ClaudeSonnet4 => Some(64_000),
|
||||
Self::ClaudeOpus4_1 => Some(32_000),
|
||||
Self::ClaudeSonnet5 => Some(128_000),
|
||||
Self::ClaudeFable5 => Some(128_000),
|
||||
|
||||
// OpenAI models
|
||||
Self::Gpt5_5
|
||||
@@ -539,7 +559,13 @@ impl Model {
|
||||
|
||||
// OpenAI-compatible models
|
||||
Self::MiniMaxM2_7 => Some(131_072),
|
||||
Self::MiniMaxM3 => Some(131_072),
|
||||
Self::MiniMaxM3 => {
|
||||
if subscription == OpenCodeSubscription::Go {
|
||||
Some(131_072)
|
||||
} else {
|
||||
Some(128_000)
|
||||
}
|
||||
}
|
||||
Self::MiniMaxM2_5 => {
|
||||
if subscription == OpenCodeSubscription::Go {
|
||||
Some(65_536)
|
||||
@@ -587,7 +613,9 @@ impl Model {
|
||||
| Self::ClaudeSonnet4_6
|
||||
| Self::ClaudeSonnet4_5
|
||||
| Self::ClaudeSonnet4
|
||||
| Self::ClaudeHaiku4_5 => true,
|
||||
| Self::ClaudeHaiku4_5
|
||||
| Self::ClaudeSonnet5
|
||||
| Self::ClaudeFable5 => true,
|
||||
|
||||
// OpenAI models support images
|
||||
Self::Gpt5_5
|
||||
@@ -649,20 +677,11 @@ impl Model {
|
||||
|
||||
pub fn supported_reasoning_effort_levels(&self) -> Option<Vec<ReasoningEffort>> {
|
||||
match self {
|
||||
Self::ClaudeOpus4_8 => Some(vec![
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
ReasoningEffort::XHigh,
|
||||
]),
|
||||
|
||||
Self::Nemotron3UltraFree | Self::MimoV2_5Pro | Self::MimoV2_5 => Some(vec![
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
]),
|
||||
|
||||
Self::DeepSeekV4Pro | Self::DeepSeekV4Flash => Some(vec![
|
||||
// Anthropic models
|
||||
Self::ClaudeFable5
|
||||
| Self::ClaudeOpus4_8
|
||||
| Self::ClaudeOpus4_7
|
||||
| Self::ClaudeSonnet5 => Some(vec![
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
@@ -670,6 +689,107 @@ impl Model {
|
||||
ReasoningEffort::Max,
|
||||
]),
|
||||
|
||||
Self::ClaudeOpus4_6 | Self::ClaudeSonnet4_6 => Some(vec![
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
ReasoningEffort::Max,
|
||||
]),
|
||||
|
||||
Self::ClaudeOpus4_5 => Some(vec![
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
]),
|
||||
|
||||
// OpenAI models
|
||||
Self::Gpt5_5
|
||||
| Self::Gpt5_4
|
||||
| Self::Gpt5_4Mini
|
||||
| Self::Gpt5_4Nano
|
||||
| Self::Gpt5_3Codex
|
||||
| Self::Gpt5_2 => Some(vec![
|
||||
ReasoningEffort::None,
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
ReasoningEffort::XHigh,
|
||||
]),
|
||||
|
||||
Self::Gpt5_5Pro | Self::Gpt5_4Pro => Some(vec![
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
ReasoningEffort::XHigh,
|
||||
]),
|
||||
|
||||
Self::Gpt5_2Codex | Self::Gpt5_3Spark | Self::Gpt5_1CodexMax => Some(vec![
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
ReasoningEffort::XHigh,
|
||||
]),
|
||||
|
||||
Self::Gpt5_1 => Some(vec![
|
||||
ReasoningEffort::None,
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
]),
|
||||
|
||||
Self::Gpt5Codex | Self::Gpt5_1Codex | Self::Gpt5_1CodexMini => Some(vec![
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
]),
|
||||
|
||||
Self::Gpt5 | Self::Gpt5Nano => Some(vec![
|
||||
ReasoningEffort::Minimal,
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
]),
|
||||
|
||||
// Google models
|
||||
Self::Gemini3Flash | Self::Gemini3_5Flash => Some(vec![
|
||||
ReasoningEffort::Minimal,
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
]),
|
||||
|
||||
Self::Gemini3_1Pro => Some(vec![
|
||||
ReasoningEffort::Low,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
]),
|
||||
|
||||
// DeepSeek models
|
||||
Self::DeepSeekV4Pro | Self::DeepSeekV4Flash => Some(vec![
|
||||
// OpenCode also supports Low&Medium but as per DeepSeek those are mapped to High
|
||||
ReasoningEffort::High,
|
||||
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,
|
||||
ReasoningEffort::Medium,
|
||||
ReasoningEffort::High,
|
||||
]),
|
||||
|
||||
// Z AI models
|
||||
Self::Glm5_2 => Some(vec![ReasoningEffort::High, ReasoningEffort::Max]),
|
||||
|
||||
Self::Custom {
|
||||
reasoning_effort_levels,
|
||||
..
|
||||
|
||||
Reference in new issue
Block a user