Settings refactor (#38367)

Co-Authored-By: Ben K <ben@zed.dev>
Co-Authored-By: Anthony <anthony@zed.dev>
Co-Authored-By: Mikayla <mikayla@zed.dev>

Release Notes:

- settings: Major internal changes to settings. The primary user-facing
effect is that some settings which did not make sense in project
settings files are no-longer read from there. (For example the inline
blame settings)

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: Anthony <anthony@zed.dev>
This commit is contained in:
Conrad Irwin
2025-09-18 16:47:23 +00:00
committed by GitHub
co-authored by Ben Kunkle Mikayla Maki Anthony
parent 0a9023bce0
commit fcdab160f9
219 changed files with 11697 additions and 11894 deletions
@@ -18,8 +18,6 @@ use language_model::{
LanguageModelToolResultContent, MessageContent, RateLimiter, Role,
};
use language_model::{LanguageModelCompletionEvent, LanguageModelToolUse, StopReason};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use std::pin::Pin;
use std::str::FromStr;
@@ -30,6 +28,8 @@ use ui::{Icon, IconName, List, Tooltip, prelude::*};
use util::{ResultExt, truncate_and_trailoff};
use zed_env_vars::{EnvVar, env_var};
pub use settings::AnthropicAvailableModel as AvailableModel;
const PROVIDER_ID: LanguageModelProviderId = language_model::ANTHROPIC_PROVIDER_ID;
const PROVIDER_NAME: LanguageModelProviderName = language_model::ANTHROPIC_PROVIDER_NAME;
@@ -40,55 +40,6 @@ pub struct AnthropicSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
/// The model's name in the Anthropic API. e.g. claude-3-5-sonnet-latest, claude-3-opus-20240229, etc
pub name: String,
/// The model's name in Zed's UI, such as in the model selector dropdown menu in the assistant panel.
pub display_name: Option<String>,
/// The model's context window size.
pub max_tokens: u64,
/// A model `name` to substitute when calling tools, in case the primary model doesn't support tool calling.
pub tool_override: Option<String>,
/// Configuration of Anthropic's caching API.
pub cache_configuration: Option<LanguageModelCacheConfiguration>,
pub max_output_tokens: Option<u64>,
pub default_temperature: Option<f32>,
#[serde(default)]
pub extra_beta_headers: Vec<String>,
/// The model's mode (e.g. thinking)
pub mode: Option<ModelMode>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum ModelMode {
#[default]
Default,
Thinking {
/// The maximum number of tokens to use for reasoning. Must be lower than the model's `max_output_tokens`.
budget_tokens: Option<u32>,
},
}
impl From<ModelMode> for AnthropicModelMode {
fn from(value: ModelMode) -> Self {
match value {
ModelMode::Default => AnthropicModelMode::Default,
ModelMode::Thinking { budget_tokens } => AnthropicModelMode::Thinking { budget_tokens },
}
}
}
impl From<AnthropicModelMode> for ModelMode {
fn from(value: AnthropicModelMode) -> Self {
match value {
AnthropicModelMode::Default => ModelMode::Default,
AnthropicModelMode::Thinking { budget_tokens } => ModelMode::Thinking { budget_tokens },
}
}
}
pub struct AnthropicLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,
@@ -237,7 +188,7 @@ impl LanguageModelProvider for AnthropicLanguageModelProvider {
max_output_tokens: model.max_output_tokens,
default_temperature: model.default_temperature,
extra_beta_headers: model.extra_beta_headers.clone(),
mode: model.mode.clone().unwrap_or_default().into(),
mode: model.mode.unwrap_or_default().into(),
},
);
}
+9 -10
View File
@@ -42,7 +42,7 @@ use language_model::{
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use settings::{Settings, SettingsStore};
use settings::{BedrockAvailableModel as AvailableModel, Settings, SettingsStore};
use smol::lock::OnceCell;
use strum::{EnumIter, IntoEnumIterator, IntoStaticStr};
use theme::ThemeSettings;
@@ -83,15 +83,14 @@ pub enum BedrockAuthMethod {
Automatic,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub cache_configuration: Option<LanguageModelCacheConfiguration>,
pub max_output_tokens: Option<u64>,
pub default_temperature: Option<f32>,
pub mode: Option<ModelMode>,
impl From<settings::BedrockAuthMethodContent> for BedrockAuthMethod {
fn from(value: settings::BedrockAuthMethodContent) -> Self {
match value {
settings::BedrockAuthMethodContent::SingleSignOn => BedrockAuthMethod::SingleSignOn,
settings::BedrockAuthMethodContent::Automatic => BedrockAuthMethod::Automatic,
settings::BedrockAuthMethodContent::NamedProfile => BedrockAuthMethod::NamedProfile,
}
}
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
+2 -36
View File
@@ -32,6 +32,8 @@ use release_channel::AppVersion;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use settings::SettingsStore;
pub use settings::ZedDotDevAvailableModel as AvailableModel;
pub use settings::ZedDotDevAvailableProvider as AvailableProvider;
use smol::io::{AsyncReadExt, BufReader};
use std::pin::Pin;
use std::str::FromStr as _;
@@ -52,42 +54,6 @@ const PROVIDER_NAME: LanguageModelProviderName = language_model::ZED_CLOUD_PROVI
pub struct ZedDotDevSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum AvailableProvider {
Anthropic,
OpenAi,
Google,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
/// The provider of the language model.
pub provider: AvailableProvider,
/// The model's name in the provider's API. e.g. claude-3-5-sonnet-20240620
pub name: String,
/// The name displayed in the UI, such as in the assistant panel model dropdown menu.
pub display_name: Option<String>,
/// The size of the context window, indicating the maximum number of tokens the model can process.
pub max_tokens: usize,
/// The maximum number of output tokens allowed by the model.
pub max_output_tokens: Option<u64>,
/// The maximum number of completion tokens allowed by the model (o1-* only)
pub max_completion_tokens: Option<u64>,
/// Override this model with a different Anthropic model for tool calls.
pub tool_override: Option<String>,
/// Indicates whether this custom model supports caching.
pub cache_configuration: Option<LanguageModelCacheConfiguration>,
/// The default temperature to use for this model.
pub default_temperature: Option<f32>,
/// Any extra beta headers to provide when using the model.
#[serde(default)]
pub extra_beta_headers: Vec<String>,
/// The model's mode (e.g. thinking)
pub mode: Option<ModelMode>,
}
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum ModelMode {
@@ -16,8 +16,7 @@ use language_model::{
LanguageModelToolChoice, LanguageModelToolResultContent, LanguageModelToolUse, MessageContent,
RateLimiter, Role, StopReason, TokenUsage,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use settings::DeepseekAvailableModel as AvailableModel;
use settings::{Settings, SettingsStore};
use std::pin::Pin;
use std::str::FromStr;
@@ -47,15 +46,6 @@ pub struct DeepSeekSettings {
pub api_url: String,
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub max_output_tokens: Option<u64>,
}
pub struct DeepSeekLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: Entity<State>,
+2 -27
View File
@@ -24,6 +24,7 @@ use language_model::{
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use settings::GoogleAvailableModel as AvailableModel;
use settings::{Settings, SettingsStore};
use std::pin::Pin;
use std::sync::{
@@ -60,32 +61,6 @@ pub enum ModelMode {
},
}
impl From<ModelMode> for GoogleModelMode {
fn from(value: ModelMode) -> Self {
match value {
ModelMode::Default => GoogleModelMode::Default,
ModelMode::Thinking { budget_tokens } => GoogleModelMode::Thinking { budget_tokens },
}
}
}
impl From<GoogleModelMode> for ModelMode {
fn from(value: GoogleModelMode) -> Self {
match value {
GoogleModelMode::Default => ModelMode::Default,
GoogleModelMode::Thinking { budget_tokens } => ModelMode::Thinking { budget_tokens },
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
name: String,
display_name: Option<String>,
max_tokens: u64,
mode: Option<ModelMode>,
}
pub struct GoogleLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,
@@ -234,7 +209,7 @@ impl LanguageModelProvider for GoogleLanguageModelProvider {
name: model.name.clone(),
display_name: model.display_name.clone(),
max_tokens: model.max_tokens,
mode: model.mode.unwrap_or_default().into(),
mode: model.mode.unwrap_or_default(),
},
);
}
@@ -15,8 +15,7 @@ use language_model::{
LanguageModelRequest, RateLimiter, Role,
};
use lmstudio::{ModelType, get_models};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use settings::LmStudioAvailableModel as AvailableModel;
use settings::{Settings, SettingsStore};
use std::pin::Pin;
use std::str::FromStr;
@@ -40,15 +39,6 @@ pub struct LmStudioSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub supports_tool_calls: bool,
pub supports_images: bool,
}
pub struct LmStudioLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,
+1 -14
View File
@@ -15,8 +15,7 @@ use language_model::{
RateLimiter, Role, StopReason, TokenUsage,
};
use mistral::{MISTRAL_API_URL, StreamResponse};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use settings::MistralAvailableModel as AvailableModel;
use settings::{Settings, SettingsStore};
use std::collections::HashMap;
use std::pin::Pin;
@@ -42,18 +41,6 @@ pub struct MistralSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub max_output_tokens: Option<u64>,
pub max_completion_tokens: Option<u64>,
pub supports_tools: Option<bool>,
pub supports_images: Option<bool>,
pub supports_thinking: Option<bool>,
}
pub struct MistralLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,
+16 -34
View File
@@ -13,12 +13,10 @@ use language_model::{
};
use menu;
use ollama::{
ChatMessage, ChatOptions, ChatRequest, ChatResponseDelta, KeepAlive, OLLAMA_API_URL,
OllamaFunctionCall, OllamaFunctionTool, OllamaToolCall, get_models, show_model,
stream_chat_completion,
ChatMessage, ChatOptions, ChatRequest, ChatResponseDelta, OLLAMA_API_URL, OllamaFunctionCall,
OllamaFunctionTool, OllamaToolCall, get_models, show_model, stream_chat_completion,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use settings::OllamaAvailableModel as AvailableModel;
use settings::{Settings, SettingsStore, update_settings_file};
use std::pin::Pin;
use std::sync::LazyLock;
@@ -48,24 +46,6 @@ pub struct OllamaSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
/// The model name in the Ollama API (e.g. "llama3.2:latest")
pub name: String,
/// The model's name in Zed's UI, such as in the model selector dropdown menu in the assistant panel.
pub display_name: Option<String>,
/// The Context Length parameter to the model (aka num_ctx or n_ctx)
pub max_tokens: u64,
/// The number of seconds to keep the connection open after the last request
pub keep_alive: Option<KeepAlive>,
/// Whether the model supports tools
pub supports_tools: Option<bool>,
/// Whether the model supports vision
pub supports_images: Option<bool>,
/// Whether to enable think mode
pub supports_thinking: Option<bool>,
}
pub struct OllamaLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,
@@ -703,15 +683,13 @@ impl ConfigurationView {
let current_url = OllamaLanguageModelProvider::api_url(cx);
if !api_url.is_empty() && &api_url != &current_url {
let fs = <dyn Fs>::global(cx);
update_settings_file::<AllLanguageModelSettings>(fs, cx, move |settings, _| {
if let Some(settings) = settings.ollama.as_mut() {
settings.api_url = Some(api_url);
} else {
settings.ollama = Some(crate::settings::OllamaSettingsContent {
api_url: Some(api_url),
available_models: None,
});
}
update_settings_file(fs, cx, move |settings, _| {
settings
.language_models
.get_or_insert_default()
.ollama
.get_or_insert_default()
.api_url = Some(api_url);
});
}
}
@@ -720,8 +698,12 @@ impl ConfigurationView {
self.api_url_editor
.update(cx, |input, cx| input.set_text("", window, cx));
let fs = <dyn Fs>::global(cx);
update_settings_file::<AllLanguageModelSettings>(fs, cx, |settings, _cx| {
if let Some(settings) = settings.ollama.as_mut() {
update_settings_file(fs, cx, |settings, _cx| {
if let Some(settings) = settings
.language_models
.as_mut()
.and_then(|models| models.ollama.as_mut())
{
settings.api_url = Some(OLLAMA_API_URL.into());
}
});
+1 -13
View File
@@ -15,9 +15,7 @@ use menu;
use open_ai::{
ImageUrl, Model, OPEN_AI_API_URL, ReasoningEffort, ResponseStreamEvent, stream_completion,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use settings::{OpenAiAvailableModel as AvailableModel, Settings, SettingsStore};
use std::pin::Pin;
use std::str::FromStr as _;
use std::sync::{Arc, LazyLock};
@@ -41,16 +39,6 @@ pub struct OpenAiSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub max_output_tokens: Option<u64>,
pub max_completion_tokens: Option<u64>,
pub reasoning_effort: Option<ReasoningEffort>,
}
pub struct OpenAiLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,
@@ -11,8 +11,6 @@ use language_model::{
};
use menu;
use open_ai::{ResponseStreamEvent, stream_completion};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use std::sync::Arc;
use ui::{ElevationIndex, Tooltip, prelude::*};
@@ -22,6 +20,8 @@ use zed_env_vars::EnvVar;
use crate::api_key::ApiKeyState;
use crate::provider::open_ai::{OpenAiEventMapper, into_open_ai};
pub use settings::OpenAiCompatibleAvailableModel as AvailableModel;
pub use settings::OpenAiCompatibleModelCapabilities as ModelCapabilities;
#[derive(Default, Clone, Debug, PartialEq)]
pub struct OpenAiCompatibleSettings {
@@ -29,36 +29,6 @@ pub struct OpenAiCompatibleSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub max_output_tokens: Option<u64>,
pub max_completion_tokens: Option<u64>,
#[serde(default)]
pub capabilities: ModelCapabilities,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ModelCapabilities {
pub tools: bool,
pub images: bool,
pub parallel_tool_calls: bool,
pub prompt_cache_key: bool,
}
impl Default for ModelCapabilities {
fn default() -> Self {
Self {
tools: true,
images: false,
parallel_tool_calls: false,
prompt_cache_key: false,
}
}
}
pub struct OpenAiCompatibleLanguageModelProvider {
id: LanguageModelProviderId,
name: LanguageModelProviderName,
@@ -14,12 +14,9 @@ use language_model::{
LanguageModelToolUse, MessageContent, RateLimiter, Role, StopReason, TokenUsage,
};
use open_router::{
Model, ModelMode as OpenRouterModelMode, OPEN_ROUTER_API_URL, Provider, ResponseStreamEvent,
list_models,
Model, ModelMode as OpenRouterModelMode, OPEN_ROUTER_API_URL, ResponseStreamEvent, list_models,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore};
use settings::{OpenRouterAvailableModel as AvailableModel, Settings, SettingsStore};
use std::pin::Pin;
use std::str::FromStr as _;
use std::sync::{Arc, LazyLock};
@@ -42,51 +39,6 @@ pub struct OpenRouterSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub max_output_tokens: Option<u64>,
pub max_completion_tokens: Option<u64>,
pub supports_tools: Option<bool>,
pub supports_images: Option<bool>,
pub mode: Option<ModelMode>,
pub provider: Option<Provider>,
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum ModelMode {
#[default]
Default,
Thinking {
budget_tokens: Option<u32>,
},
}
impl From<ModelMode> for OpenRouterModelMode {
fn from(value: ModelMode) -> Self {
match value {
ModelMode::Default => OpenRouterModelMode::Default,
ModelMode::Thinking { budget_tokens } => {
OpenRouterModelMode::Thinking { budget_tokens }
}
}
}
}
impl From<OpenRouterModelMode> for ModelMode {
fn from(value: OpenRouterModelMode) -> Self {
match value {
OpenRouterModelMode::Default => ModelMode::Default,
OpenRouterModelMode::Thinking { budget_tokens } => {
ModelMode::Thinking { budget_tokens }
}
}
}
}
pub struct OpenRouterLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,
@@ -259,7 +211,7 @@ impl LanguageModelProvider for OpenRouterLanguageModelProvider {
max_tokens: model.max_tokens,
supports_tools: model.supports_tools,
supports_images: model.supports_images,
mode: model.mode.clone().unwrap_or_default().into(),
mode: model.mode.unwrap_or_default(),
provider: model.provider.clone(),
});
}
+2 -12
View File
@@ -10,8 +10,7 @@ use language_model::{
LanguageModelToolChoice, RateLimiter, Role,
};
use open_ai::ResponseStreamEvent;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use settings::VercelAvailableModel as AvailableModel;
use settings::{Settings, SettingsStore};
use std::sync::{Arc, LazyLock};
use strum::IntoEnumIterator;
@@ -29,21 +28,12 @@ const PROVIDER_NAME: LanguageModelProviderName = LanguageModelProviderName::new(
const API_KEY_ENV_VAR_NAME: &str = "VERCEL_API_KEY";
static API_KEY_ENV_VAR: LazyLock<EnvVar> = env_var!(API_KEY_ENV_VAR_NAME);
#[derive(Default, Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct VercelSettings {
pub api_url: String,
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub max_output_tokens: Option<u64>,
pub max_completion_tokens: Option<u64>,
}
pub struct VercelLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,
+1 -11
View File
@@ -10,8 +10,7 @@ use language_model::{
LanguageModelToolChoice, LanguageModelToolSchemaFormat, RateLimiter, Role,
};
use open_ai::ResponseStreamEvent;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub use settings::XaiAvailableModel as AvailableModel;
use settings::{Settings, SettingsStore};
use std::sync::{Arc, LazyLock};
use strum::IntoEnumIterator;
@@ -35,15 +34,6 @@ pub struct XAiSettings {
pub available_models: Vec<AvailableModel>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
pub name: String,
pub display_name: Option<String>,
pub max_tokens: u64,
pub max_output_tokens: Option<u64>,
pub max_completion_tokens: Option<u64>,
}
pub struct XAiLanguageModelProvider {
http_client: Arc<dyn HttpClient>,
state: gpui::Entity<State>,