use std::{ path::{Path, PathBuf}, sync::Arc,}; use anyhow::Context;use collections::{BTreeMap, HashMap};use gpui::Rgba;use schemars::JsonSchema;use serde::{Deserialize, Serialize};use settings_json::parse_json_with_comments;use settings_macros::{MergeFrom, with_fallible_options};use util::serde::default_true; use crate::{ AllLanguageSettingsContent, DelayMs, ExtendingVec, ParseStatus, ProjectTerminalSettingsContent, RootUserSettings, SaturatingBool, fallible_options,}; #[with_fallible_options]#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]pub struct LspSettingsMap(pub HashMap<Arc<str>, LspSettings>); impl IntoIterator for LspSettingsMap { type Item = (Arc<str>, LspSettings); type IntoIter = std::collections::hash_map::IntoIter<Arc<str>, LspSettings>; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }} impl RootUserSettings for ProjectSettingsContent { fn parse_json(json: &str) -> (Option<Self>, ParseStatus) { fallible_options::parse_json(json) } fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> { parse_json_with_comments(json) }} #[with_fallible_options]#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]pub struct ProjectSettingsContent { #[serde(flatten)] pub all_languages: AllLanguageSettingsContent, #[serde(flatten)] pub worktree: WorktreeSettingsContent, /// Configuration for language servers. /// /// The following settings can be overridden for specific language servers: /// - initialization_options /// /// To override settings for a language, add an entry for that language server's /// name to the lsp value. /// Default: null #[serde(default)] pub lsp: LspSettingsMap, pub terminal: Option<ProjectTerminalSettingsContent>, /// Configuration for Debugger-related features #[serde(default)] pub dap: HashMap<Arc<str>, DapSettingsContent>, /// Settings for context servers used for AI-related features. #[serde(default)] pub context_servers: HashMap<Arc<str>, ContextServerSettingsContent>, /// Default timeout in seconds for context server tool calls. /// Can be overridden per-server in context_servers configuration. /// /// Default: 60 pub context_server_timeout: Option<u64>, /// Configuration for how direnv configuration should be loaded pub load_direnv: Option<DirenvSettings>, /// The list of custom Git hosting providers. pub git_hosting_providers: Option<ExtendingVec<GitHostingProviderConfig>>, /// Whether to disable all AI features in Zed. /// /// Default: false pub disable_ai: Option<SaturatingBool>,} /// When to scan content of linked directories.#[derive( Copy, Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames,)]#[serde(rename_all = "snake_case")]pub enum ScanSymlinksSetting { /// Always scan symlinked directories Always, /// Only scan symlinked directories when they've been expanded in the workspace #[default] Expanded,} #[with_fallible_options]#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]pub struct WorktreeSettingsContent { /// Whether to prevent this project from being shared in public channels. /// /// Default: false #[serde(default)] pub prevent_sharing_in_public_channels: bool, /// Completely ignore files matching globs from `file_scan_exclusions`. Overrides /// `file_scan_inclusions`. /// /// Default: [ /// "**/.git", /// "**/.svn", /// "**/.hg", /// "**/.jj", /// "**/CVS", /// "**/.DS_Store", /// "**/Thumbs.db", /// "**/.classpath", /// "**/.settings" /// ] pub file_scan_exclusions: Option<Vec<String>>, /// Always include files that match these globs when scanning for files, even if they're /// ignored by git. This setting is overridden by `file_scan_exclusions`. /// Default: [ /// ".env*", /// "docker-compose.*.yml", /// ] pub file_scan_inclusions: Option<Vec<String>>, /// When to scan content of linked directories. /// /// Default: expanded pub scan_symlinks: Option<ScanSymlinksSetting>, /// Treat the files matching these globs as `.env` files. /// Default: ["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/secrets.yml"] pub private_files: Option<ExtendingVec<String>>, /// Treat the files matching these globs as hidden files. You can hide hidden files in the project panel. /// Default: ["**/.*"] pub hidden_files: Option<Vec<String>>, /// Treat the files matching these globs as read-only. These files can be opened and viewed, /// but cannot be edited. This is useful for generated files, build outputs, or files from /// external dependencies that should not be modified directly. /// Default: [] pub read_only_files: Option<Vec<String>>,} #[with_fallible_options]#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash)]#[serde(rename_all = "snake_case")]pub struct LspSettings { pub binary: Option<BinarySettings>, /// Options passed to the language server at startup. /// /// Ref: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize /// /// Consult the documentation for the specific language server to see which settings are supported. pub initialization_options: Option<serde_json::Value>, /// Language server settings. /// /// Ref: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration /// /// Consult the documentation for the specific language server to see which settings are supported. pub settings: Option<serde_json::Value>, /// If the server supports sending tasks over LSP extensions, /// this setting can be used to enable or disable them in Zed. /// Default: true #[serde(default = "default_true")] pub enable_lsp_tasks: bool, pub fetch: Option<FetchSettings>,} impl Default for LspSettings { fn default() -> Self { Self { binary: None, initialization_options: None, settings: None, enable_lsp_tasks: true, fetch: None, } }} #[with_fallible_options]#[derive( Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,)]pub struct BinarySettings { pub path: Option<String>, pub arguments: Option<Vec<String>>, pub env: Option<BTreeMap<String, String>>, pub ignore_system_version: Option<bool>,} #[with_fallible_options]#[derive( Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash,)]pub struct FetchSettings { // Whether to consider pre-releases for fetching pub pre_release: Option<bool>,} /// Common language server settings.#[with_fallible_options]#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]pub struct GlobalLspSettingsContent { /// Whether to show the LSP servers button in the status bar. /// /// Default: `true` pub button: Option<bool>, /// The maximum amount of time to wait for responses from language servers, in seconds. /// A value of `0` will result in no timeout being applied (causing all LSP responses to wait indefinitely until completed). /// /// Default: `120` pub request_timeout: Option<u64>, /// Settings for language server notifications pub notifications: Option<LspNotificationSettingsContent>, /// Rules for rendering LSP semantic tokens. pub semantic_token_rules: Option<SemanticTokenRules>,} #[with_fallible_options]#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]pub struct LspNotificationSettingsContent { /// Timeout in milliseconds for automatically dismissing language server notifications. /// Set to 0 to disable auto-dismiss. /// /// Default: 5000 pub dismiss_timeout_ms: Option<u64>,} /// Custom rules for rendering LSP semantic tokens.#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)]#[serde(transparent)]pub struct SemanticTokenRules { pub rules: Vec<SemanticTokenRule>,} impl SemanticTokenRules { pub const FILE_NAME: &'static str = "semantic_token_rules.json"; pub fn load(file_path: &Path) -> anyhow::Result<Self> { let rules_content = std::fs::read(file_path).with_context(|| { anyhow::anyhow!( "Could not read semantic token rules from {}", file_path.display() ) })?; serde_json_lenient::from_slice::<SemanticTokenRules>(&rules_content).with_context(|| { anyhow::anyhow!( "Failed to parse semantic token rules from {}", file_path.display() ) }) }} impl crate::merge_from::MergeFrom for SemanticTokenRules { fn merge_from(&mut self, other: &Self) { self.rules.splice(0..0, other.rules.iter().cloned()); }} #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)]#[serde(rename_all = "snake_case")]pub struct SemanticTokenRule { pub token_type: Option<String>, #[serde(default)] pub token_modifiers: Vec<String>, #[serde(default)] pub style: Vec<String>, pub foreground_color: Option<Rgba>, pub background_color: Option<Rgba>, pub underline: Option<SemanticTokenColorOverride>, pub strikethrough: Option<SemanticTokenColorOverride>, pub font_weight: Option<SemanticTokenFontWeight>, pub font_style: Option<SemanticTokenFontStyle>,} impl SemanticTokenRule { pub fn no_style_defined(&self) -> bool { self.style.is_empty() && self.foreground_color.is_none() && self.background_color.is_none() && self.underline.is_none() && self.strikethrough.is_none() && self.font_weight.is_none() && self.font_style.is_none() }} #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)]#[serde(untagged)]pub enum SemanticTokenColorOverride { InheritForeground(bool), Replace(Rgba),} #[derive( Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames,)]#[serde(rename_all = "snake_case")]pub enum SemanticTokenFontWeight { #[default] Normal, Bold,} #[derive( Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames,)]#[serde(rename_all = "snake_case")]pub enum SemanticTokenFontStyle { #[default] Normal, Italic,} #[with_fallible_options]#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)]#[serde(rename_all = "snake_case")]pub struct DapSettingsContent { pub binary: Option<String>, pub args: Option<Vec<String>>, pub env: Option<HashMap<String, String>>,} #[with_fallible_options]#[derive( Default, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema, MergeFrom,)]pub struct SessionSettingsContent { /// Whether or not to restore unsaved buffers on restart. /// /// If this is true, user won't be prompted whether to save/discard /// dirty files when closing the application. /// /// Default: true pub restore_unsaved_buffers: Option<bool>, /// Whether or not to skip worktree trust checks. /// When trusted, project settings are synchronized automatically, /// language and MCP servers are downloaded and started automatically. /// /// Default: false pub trust_all_worktrees: Option<bool>,} #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom, Debug)]#[serde(untagged, rename_all = "snake_case")]pub enum ContextServerSettingsContent { Stdio { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// Whether to run the context server on the remote server when using remote development. /// /// If this is false, the context server will always run on the local machine. /// /// Default: false #[serde(default)] remote: bool, #[serde(flatten)] command: ContextServerCommand, }, Http { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// The URL of the remote context server. url: String, /// Optional headers to send. #[serde(skip_serializing_if = "HashMap::is_empty", default)] headers: HashMap<String, String>, /// Timeout for tool calls in seconds. Defaults to global context_server_timeout if not specified. timeout: Option<u64>, /// Pre-registered OAuth client credentials for authorization servers that /// require out-of-band client registration. #[serde(default, skip_serializing_if = "Option::is_none")] oauth: Option<OAuthClientSettings>, }, Extension { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// Whether to run the context server on the remote server when using remote development. /// /// If this is false, the context server will always run on the local machine. /// /// Default: false #[serde(default)] remote: bool, /// The settings for this context server specified by the extension. /// /// Consult the documentation for the context server to see what settings /// are supported. settings: serde_json::Value, },} impl ContextServerSettingsContent { pub fn set_enabled(&mut self, enabled: bool) { match self { ContextServerSettingsContent::Stdio { enabled: custom_enabled, .. } => { *custom_enabled = enabled; } ContextServerSettingsContent::Extension { enabled: ext_enabled, .. } => *ext_enabled = enabled, ContextServerSettingsContent::Http { enabled: remote_enabled, .. } => *remote_enabled = enabled, } }} /// Pre-registered OAuth client credentials for MCP servers that don't support/// Dynamic Client Registration.#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom, Debug)]pub struct OAuthClientSettings { /// The OAuth client ID obtained from out-of-band registration with the /// authorization server. pub client_id: String, /// The OAuth client secret, if this is a confidential client. For security, /// prefer providing this interactively; we will prompt and store it in /// the system keychain. #[serde(default, skip_serializing_if = "Option::is_none")] pub client_secret: Option<String>,} #[with_fallible_options]#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom)]pub struct ContextServerCommand { #[serde(rename = "command")] pub path: PathBuf, #[serde(default)] pub args: Vec<String>, pub env: Option<HashMap<String, String>>, /// Timeout for tool calls in seconds. Defaults to 60 if not specified. pub timeout: Option<u64>,} impl std::fmt::Debug for ContextServerCommand { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let filtered_env = self.env.as_ref().map(|env| { env.iter() .map(|(k, v)| { ( k, if util::redact::should_redact(k) { "[REDACTED]" } else {Lines 1–500 of 900. Load more
use std::{ path::{Path, PathBuf}, sync::Arc, }; use anyhow::Context; use collections::{BTreeMap, HashMap}; use gpui::Rgba; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings_json::parse_json_with_comments; use settings_macros::{MergeFrom, with_fallible_options}; use util::serde::default_true; use crate::{ AllLanguageSettingsContent, DelayMs, ExtendingVec, ParseStatus, ProjectTerminalSettingsContent, RootUserSettings, SaturatingBool, fallible_options, }; #[with_fallible_options] #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct LspSettingsMap(pub HashMap<Arc<str>, LspSettings>); impl IntoIterator for LspSettingsMap { type Item = (Arc<str>, LspSettings); type IntoIter = std::collections::hash_map::IntoIter<Arc<str>, LspSettings>; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } impl RootUserSettings for ProjectSettingsContent { fn parse_json(json: &str) -> (Option<Self>, ParseStatus) { fallible_options::parse_json(json) } fn parse_json_with_comments(json: &str) -> anyhow::Result<Self> { parse_json_with_comments(json) } } #[with_fallible_options] #[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct ProjectSettingsContent { #[serde(flatten)] pub all_languages: AllLanguageSettingsContent, #[serde(flatten)] pub worktree: WorktreeSettingsContent, /// Configuration for language servers. /// /// The following settings can be overridden for specific language servers: /// - initialization_options /// /// To override settings for a language, add an entry for that language server's /// name to the lsp value. /// Default: null #[serde(default)] pub lsp: LspSettingsMap, pub terminal: Option<ProjectTerminalSettingsContent>, /// Configuration for Debugger-related features #[serde(default)] pub dap: HashMap<Arc<str>, DapSettingsContent>, /// Settings for context servers used for AI-related features. #[serde(default)] pub context_servers: HashMap<Arc<str>, ContextServerSettingsContent>, /// Default timeout in seconds for context server tool calls. /// Can be overridden per-server in context_servers configuration. /// /// Default: 60 pub context_server_timeout: Option<u64>, /// Configuration for how direnv configuration should be loaded pub load_direnv: Option<DirenvSettings>, /// The list of custom Git hosting providers. pub git_hosting_providers: Option<ExtendingVec<GitHostingProviderConfig>>, /// Whether to disable all AI features in Zed. /// /// Default: false pub disable_ai: Option<SaturatingBool>, } /// When to scan content of linked directories. #[derive( Copy, Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum ScanSymlinksSetting { /// Always scan symlinked directories Always, /// Only scan symlinked directories when they've been expanded in the workspace #[default] Expanded, } #[with_fallible_options] #[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct WorktreeSettingsContent { /// Whether to prevent this project from being shared in public channels. /// /// Default: false #[serde(default)] pub prevent_sharing_in_public_channels: bool, /// Completely ignore files matching globs from `file_scan_exclusions`. Overrides /// `file_scan_inclusions`. /// /// Default: [ /// "**/.git", /// "**/.svn", /// "**/.hg", /// "**/.jj", /// "**/CVS", /// "**/.DS_Store", /// "**/Thumbs.db", /// "**/.classpath", /// "**/.settings" /// ] pub file_scan_exclusions: Option<Vec<String>>, /// Always include files that match these globs when scanning for files, even if they're /// ignored by git. This setting is overridden by `file_scan_exclusions`. /// Default: [ /// ".env*", /// "docker-compose.*.yml", /// ] pub file_scan_inclusions: Option<Vec<String>>, /// When to scan content of linked directories. /// /// Default: expanded pub scan_symlinks: Option<ScanSymlinksSetting>, /// Treat the files matching these globs as `.env` files. /// Default: ["**/.env*", "**/*.pem", "**/*.key", "**/*.cert", "**/*.crt", "**/secrets.yml"] pub private_files: Option<ExtendingVec<String>>, /// Treat the files matching these globs as hidden files. You can hide hidden files in the project panel. /// Default: ["**/.*"] pub hidden_files: Option<Vec<String>>, /// Treat the files matching these globs as read-only. These files can be opened and viewed, /// but cannot be edited. This is useful for generated files, build outputs, or files from /// external dependencies that should not be modified directly. /// Default: [] pub read_only_files: Option<Vec<String>>, } #[with_fallible_options] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash)] #[serde(rename_all = "snake_case")] pub struct LspSettings { pub binary: Option<BinarySettings>, /// Options passed to the language server at startup. /// /// Ref: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize /// /// Consult the documentation for the specific language server to see which settings are supported. pub initialization_options: Option<serde_json::Value>, /// Language server settings. /// /// Ref: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration /// /// Consult the documentation for the specific language server to see which settings are supported. pub settings: Option<serde_json::Value>, /// If the server supports sending tasks over LSP extensions, /// this setting can be used to enable or disable them in Zed. /// Default: true #[serde(default = "default_true")] pub enable_lsp_tasks: bool, pub fetch: Option<FetchSettings>, } impl Default for LspSettings { fn default() -> Self { Self { binary: None, initialization_options: None, settings: None, enable_lsp_tasks: true, fetch: None, } } } #[with_fallible_options] #[derive( Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash, )] pub struct BinarySettings { pub path: Option<String>, pub arguments: Option<Vec<String>>, pub env: Option<BTreeMap<String, String>>, pub ignore_system_version: Option<bool>, } #[with_fallible_options] #[derive( Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, Hash, )] pub struct FetchSettings { // Whether to consider pre-releases for fetching pub pre_release: Option<bool>, } /// Common language server settings. #[with_fallible_options] #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct GlobalLspSettingsContent { /// Whether to show the LSP servers button in the status bar. /// /// Default: `true` pub button: Option<bool>, /// The maximum amount of time to wait for responses from language servers, in seconds. /// A value of `0` will result in no timeout being applied (causing all LSP responses to wait indefinitely until completed). /// /// Default: `120` pub request_timeout: Option<u64>, /// Settings for language server notifications pub notifications: Option<LspNotificationSettingsContent>, /// Rules for rendering LSP semantic tokens. pub semantic_token_rules: Option<SemanticTokenRules>, } #[with_fallible_options] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)] pub struct LspNotificationSettingsContent { /// Timeout in milliseconds for automatically dismissing language server notifications. /// Set to 0 to disable auto-dismiss. /// /// Default: 5000 pub dismiss_timeout_ms: Option<u64>, } /// Custom rules for rendering LSP semantic tokens. #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)] #[serde(transparent)] pub struct SemanticTokenRules { pub rules: Vec<SemanticTokenRule>, } impl SemanticTokenRules { pub const FILE_NAME: &'static str = "semantic_token_rules.json"; pub fn load(file_path: &Path) -> anyhow::Result<Self> { let rules_content = std::fs::read(file_path).with_context(|| { anyhow::anyhow!( "Could not read semantic token rules from {}", file_path.display() ) })?; serde_json_lenient::from_slice::<SemanticTokenRules>(&rules_content).with_context(|| { anyhow::anyhow!( "Failed to parse semantic token rules from {}", file_path.display() ) }) } } impl crate::merge_from::MergeFrom for SemanticTokenRules { fn merge_from(&mut self, other: &Self) { self.rules.splice(0..0, other.rules.iter().cloned()); } } #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct SemanticTokenRule { pub token_type: Option<String>, #[serde(default)] pub token_modifiers: Vec<String>, #[serde(default)] pub style: Vec<String>, pub foreground_color: Option<Rgba>, pub background_color: Option<Rgba>, pub underline: Option<SemanticTokenColorOverride>, pub strikethrough: Option<SemanticTokenColorOverride>, pub font_weight: Option<SemanticTokenFontWeight>, pub font_style: Option<SemanticTokenFontStyle>, } impl SemanticTokenRule { pub fn no_style_defined(&self) -> bool { self.style.is_empty() && self.foreground_color.is_none() && self.background_color.is_none() && self.underline.is_none() && self.strikethrough.is_none() && self.font_weight.is_none() && self.font_style.is_none() } } #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, MergeFrom)] #[serde(untagged)] pub enum SemanticTokenColorOverride { InheritForeground(bool), Replace(Rgba), } #[derive( Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum SemanticTokenFontWeight { #[default] Normal, Bold, } #[derive( Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, MergeFrom, strum::VariantArray, strum::VariantNames, )] #[serde(rename_all = "snake_case")] pub enum SemanticTokenFontStyle { #[default] Normal, Italic, } #[with_fallible_options] #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema, MergeFrom)] #[serde(rename_all = "snake_case")] pub struct DapSettingsContent { pub binary: Option<String>, pub args: Option<Vec<String>>, pub env: Option<HashMap<String, String>>, } #[with_fallible_options] #[derive( Default, Copy, Clone, PartialEq, Eq, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, )] pub struct SessionSettingsContent { /// Whether or not to restore unsaved buffers on restart. /// /// If this is true, user won't be prompted whether to save/discard /// dirty files when closing the application. /// /// Default: true pub restore_unsaved_buffers: Option<bool>, /// Whether or not to skip worktree trust checks. /// When trusted, project settings are synchronized automatically, /// language and MCP servers are downloaded and started automatically. /// /// Default: false pub trust_all_worktrees: Option<bool>, } #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom, Debug)] #[serde(untagged, rename_all = "snake_case")] pub enum ContextServerSettingsContent { Stdio { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// Whether to run the context server on the remote server when using remote development. /// /// If this is false, the context server will always run on the local machine. /// /// Default: false #[serde(default)] remote: bool, #[serde(flatten)] command: ContextServerCommand, }, Http { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// The URL of the remote context server. url: String, /// Optional headers to send. #[serde(skip_serializing_if = "HashMap::is_empty", default)] headers: HashMap<String, String>, /// Timeout for tool calls in seconds. Defaults to global context_server_timeout if not specified. timeout: Option<u64>, /// Pre-registered OAuth client credentials for authorization servers that /// require out-of-band client registration. #[serde(default, skip_serializing_if = "Option::is_none")] oauth: Option<OAuthClientSettings>, }, Extension { /// Whether the context server is enabled. #[serde(default = "default_true")] enabled: bool, /// Whether to run the context server on the remote server when using remote development. /// /// If this is false, the context server will always run on the local machine. /// /// Default: false #[serde(default)] remote: bool, /// The settings for this context server specified by the extension. /// /// Consult the documentation for the context server to see what settings /// are supported. settings: serde_json::Value, }, } impl ContextServerSettingsContent { pub fn set_enabled(&mut self, enabled: bool) { match self { ContextServerSettingsContent::Stdio { enabled: custom_enabled, .. } => { *custom_enabled = enabled; } ContextServerSettingsContent::Extension { enabled: ext_enabled, .. } => *ext_enabled = enabled, ContextServerSettingsContent::Http { enabled: remote_enabled, .. } => *remote_enabled = enabled, } } } /// Pre-registered OAuth client credentials for MCP servers that don't support /// Dynamic Client Registration. #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom, Debug)] pub struct OAuthClientSettings { /// The OAuth client ID obtained from out-of-band registration with the /// authorization server. pub client_id: String, /// The OAuth client secret, if this is a confidential client. For security, /// prefer providing this interactively; we will prompt and store it in /// the system keychain. #[serde(default, skip_serializing_if = "Option::is_none")] pub client_secret: Option<String>, } #[with_fallible_options] #[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema, MergeFrom)] pub struct ContextServerCommand { #[serde(rename = "command")] pub path: PathBuf, #[serde(default)] pub args: Vec<String>, pub env: Option<HashMap<String, String>>, /// Timeout for tool calls in seconds. Defaults to 60 if not specified. pub timeout: Option<u64>, } impl std::fmt::Debug for ContextServerCommand { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let filtered_env = self.env.as_ref().map(|env| { env.iter() .map(|(k, v)| { ( k, if util::redact::should_redact(k) { "[REDACTED]" } else {