settings.rs

  1use std::path::PathBuf;
  2
  3use crate::AgentServerCommand;
  4use anyhow::Result;
  5use collections::HashMap;
  6use gpui::{App, SharedString};
  7use schemars::JsonSchema;
  8use serde::{Deserialize, Serialize};
  9use settings::{Settings, SettingsKey, SettingsSources, SettingsUi};
 10
 11pub fn init(cx: &mut App) {
 12    AllAgentServersSettings::register(cx);
 13}
 14
 15#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, Debug, SettingsUi, SettingsKey)]
 16#[settings_key(key = "agent_servers")]
 17pub struct AllAgentServersSettings {
 18    pub gemini: Option<BuiltinAgentServerSettings>,
 19    pub claude: Option<CustomAgentServerSettings>,
 20
 21    /// Custom agent servers configured by the user
 22    #[serde(flatten)]
 23    pub custom: HashMap<SharedString, CustomAgentServerSettings>,
 24}
 25
 26#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, Debug, PartialEq)]
 27pub struct BuiltinAgentServerSettings {
 28    /// Absolute path to a binary to be used when launching this agent.
 29    ///
 30    /// This can be used to run a specific binary without automatic downloads or searching `$PATH`.
 31    #[serde(rename = "command")]
 32    pub path: Option<PathBuf>,
 33    /// If a binary is specified in `command`, it will be passed these arguments.
 34    pub args: Option<Vec<String>>,
 35    /// If a binary is specified in `command`, it will be passed these environment variables.
 36    pub env: Option<HashMap<String, String>>,
 37    /// Whether to skip searching `$PATH` for an agent server binary when
 38    /// launching this agent.
 39    ///
 40    /// This has no effect if a `command` is specified. Otherwise, when this is
 41    /// `false`, Zed will search `$PATH` for an agent server binary and, if one
 42    /// is found, use it for threads with this agent. If no agent binary is
 43    /// found on `$PATH`, Zed will automatically install and use its own binary.
 44    /// When this is `true`, Zed will not search `$PATH`, and will always use
 45    /// its own binary.
 46    ///
 47    /// Default: true
 48    pub ignore_system_version: Option<bool>,
 49}
 50
 51impl BuiltinAgentServerSettings {
 52    pub(crate) fn custom_command(self) -> Option<AgentServerCommand> {
 53        self.path.map(|path| AgentServerCommand {
 54            path,
 55            args: self.args.unwrap_or_default(),
 56            env: self.env,
 57        })
 58    }
 59}
 60
 61impl From<AgentServerCommand> for BuiltinAgentServerSettings {
 62    fn from(value: AgentServerCommand) -> Self {
 63        BuiltinAgentServerSettings {
 64            path: Some(value.path),
 65            args: Some(value.args),
 66            env: value.env,
 67            ..Default::default()
 68        }
 69    }
 70}
 71
 72#[derive(Deserialize, Serialize, Clone, JsonSchema, Debug, PartialEq)]
 73pub struct CustomAgentServerSettings {
 74    #[serde(flatten)]
 75    pub command: AgentServerCommand,
 76}
 77
 78impl settings::Settings for AllAgentServersSettings {
 79    type FileContent = Self;
 80
 81    fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
 82        let mut settings = AllAgentServersSettings::default();
 83
 84        for AllAgentServersSettings {
 85            gemini,
 86            claude,
 87            custom,
 88        } in sources.defaults_and_customizations()
 89        {
 90            if gemini.is_some() {
 91                settings.gemini = gemini.clone();
 92            }
 93            if claude.is_some() {
 94                settings.claude = claude.clone();
 95            }
 96
 97            // Merge custom agents
 98            for (name, config) in custom {
 99                // Skip built-in agent names to avoid conflicts
100                if name != "gemini" && name != "claude" {
101                    settings.custom.insert(name.clone(), config.clone());
102                }
103            }
104        }
105
106        Ok(settings)
107    }
108
109    fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {}
110}