795 lines · 30.1 KB · Rust
RawDownload
mod agent_profile; use std::sync::Arc; use ::open_ai::Model as OpenAiModel;use anthropic::Model as AnthropicModel;use anyhow::{Result, bail};use deepseek::Model as DeepseekModel;use feature_flags::{Assistant2FeatureFlag, FeatureFlagAppExt};use gpui::{App, Pixels};use indexmap::IndexMap;use language_model::{CloudModel, LanguageModel};use lmstudio::Model as LmStudioModel;use ollama::Model as OllamaModel;use schemars::{JsonSchema, schema::Schema};use serde::{Deserialize, Serialize};use settings::{Settings, SettingsSources}; pub use crate::agent_profile::*; #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]#[serde(rename_all = "snake_case")]pub enum AssistantDockPosition {    Left,    #[default]    Right,    Bottom,} #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]#[serde(rename_all = "snake_case")]pub enum NotifyWhenAgentWaiting {    #[default]    PrimaryScreen,    AllScreens,    Never,} #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]#[serde(tag = "name", rename_all = "snake_case")]pub enum AssistantProviderContentV1 {    #[serde(rename = "zed.dev")]    ZedDotDev { default_model: Option<CloudModel> },    #[serde(rename = "openai")]    OpenAi {        default_model: Option<OpenAiModel>,        api_url: Option<String>,        available_models: Option<Vec<OpenAiModel>>,    },    #[serde(rename = "anthropic")]    Anthropic {        default_model: Option<AnthropicModel>,        api_url: Option<String>,    },    #[serde(rename = "ollama")]    Ollama {        default_model: Option<OllamaModel>,        api_url: Option<String>,    },    #[serde(rename = "lmstudio")]    LmStudio {        default_model: Option<LmStudioModel>,        api_url: Option<String>,    },    #[serde(rename = "deepseek")]    DeepSeek {        default_model: Option<DeepseekModel>,        api_url: Option<String>,    },} #[derive(Clone, Debug, Default)]pub struct AssistantSettings {    pub enabled: bool,    pub button: bool,    pub dock: AssistantDockPosition,    pub default_width: Pixels,    pub default_height: Pixels,    pub default_model: LanguageModelSelection,    pub inline_assistant_model: Option<LanguageModelSelection>,    pub commit_message_model: Option<LanguageModelSelection>,    pub thread_summary_model: Option<LanguageModelSelection>,    pub inline_alternatives: Vec<LanguageModelSelection>,    pub using_outdated_settings_version: bool,    pub enable_experimental_live_diffs: bool,    pub default_profile: AgentProfileId,    pub profiles: IndexMap<AgentProfileId, AgentProfile>,    pub always_allow_tool_actions: bool,    pub notify_when_agent_waiting: NotifyWhenAgentWaiting,} impl AssistantSettings {    pub fn are_live_diffs_enabled(&self, cx: &App) -> bool {        if cx.has_flag::<Assistant2FeatureFlag>() {            return false;        }         cx.is_staff() || self.enable_experimental_live_diffs    }     pub fn set_inline_assistant_model(&mut self, provider: String, model: String) {        self.inline_assistant_model = Some(LanguageModelSelection { provider, model });    }     pub fn set_commit_message_model(&mut self, provider: String, model: String) {        self.commit_message_model = Some(LanguageModelSelection { provider, model });    }     pub fn set_thread_summary_model(&mut self, provider: String, model: String) {        self.thread_summary_model = Some(LanguageModelSelection { provider, model });    }} /// Assistant panel settings#[derive(Clone, Serialize, Deserialize, Debug)]#[serde(untagged)]pub enum AssistantSettingsContent {    Versioned(Box<VersionedAssistantSettingsContent>),    Legacy(LegacyAssistantSettingsContent),} impl JsonSchema for AssistantSettingsContent {    fn schema_name() -> String {        VersionedAssistantSettingsContent::schema_name()    }     fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> Schema {        VersionedAssistantSettingsContent::json_schema(r#gen)    }     fn is_referenceable() -> bool {        VersionedAssistantSettingsContent::is_referenceable()    }} impl Default for AssistantSettingsContent {    fn default() -> Self {        Self::Versioned(Box::new(VersionedAssistantSettingsContent::default()))    }} impl AssistantSettingsContent {    pub fn is_version_outdated(&self) -> bool {        match self {            AssistantSettingsContent::Versioned(settings) => match **settings {                VersionedAssistantSettingsContent::V1(_) => true,                VersionedAssistantSettingsContent::V2(_) => false,            },            AssistantSettingsContent::Legacy(_) => true,        }    }     fn upgrade(&self) -> AssistantSettingsContentV2 {        match self {            AssistantSettingsContent::Versioned(settings) => match **settings {                VersionedAssistantSettingsContent::V1(ref settings) => AssistantSettingsContentV2 {                    enabled: settings.enabled,                    button: settings.button,                    dock: settings.dock,                    default_width: settings.default_width,                    default_height: settings.default_width,                    default_model: settings                        .provider                        .clone()                        .and_then(|provider| match provider {                            AssistantProviderContentV1::ZedDotDev { default_model } => {                                default_model.map(|model| LanguageModelSelection {                                    provider: "zed.dev".to_string(),                                    model: model.id().to_string(),                                })                            }                            AssistantProviderContentV1::OpenAi { default_model, .. } => {                                default_model.map(|model| LanguageModelSelection {                                    provider: "openai".to_string(),                                    model: model.id().to_string(),                                })                            }                            AssistantProviderContentV1::Anthropic { default_model, .. } => {                                default_model.map(|model| LanguageModelSelection {                                    provider: "anthropic".to_string(),                                    model: model.id().to_string(),                                })                            }                            AssistantProviderContentV1::Ollama { default_model, .. } => {                                default_model.map(|model| LanguageModelSelection {                                    provider: "ollama".to_string(),                                    model: model.id().to_string(),                                })                            }                            AssistantProviderContentV1::LmStudio { default_model, .. } => {                                default_model.map(|model| LanguageModelSelection {                                    provider: "lmstudio".to_string(),                                    model: model.id().to_string(),                                })                            }                            AssistantProviderContentV1::DeepSeek { default_model, .. } => {                                default_model.map(|model| LanguageModelSelection {                                    provider: "deepseek".to_string(),                                    model: model.id().to_string(),                                })                            }                        }),                    inline_assistant_model: None,                    commit_message_model: None,                    thread_summary_model: None,                    inline_alternatives: None,                    enable_experimental_live_diffs: None,                    default_profile: None,                    profiles: None,                    always_allow_tool_actions: None,                    notify_when_agent_waiting: None,                },                VersionedAssistantSettingsContent::V2(ref settings) => settings.clone(),            },            AssistantSettingsContent::Legacy(settings) => AssistantSettingsContentV2 {                enabled: None,                button: settings.button,                dock: settings.dock,                default_width: settings.default_width,                default_height: settings.default_height,                default_model: Some(LanguageModelSelection {                    provider: "openai".to_string(),                    model: settings                        .default_open_ai_model                        .clone()                        .unwrap_or_default()                        .id()                        .to_string(),                }),                inline_assistant_model: None,                commit_message_model: None,                thread_summary_model: None,                inline_alternatives: None,                enable_experimental_live_diffs: None,                default_profile: None,                profiles: None,                always_allow_tool_actions: None,                notify_when_agent_waiting: None,            },        }    }     pub fn set_dock(&mut self, dock: AssistantDockPosition) {        match self {            AssistantSettingsContent::Versioned(settings) => match **settings {                VersionedAssistantSettingsContent::V1(ref mut settings) => {                    settings.dock = Some(dock);                }                VersionedAssistantSettingsContent::V2(ref mut settings) => {                    settings.dock = Some(dock);                }            },            AssistantSettingsContent::Legacy(settings) => {                settings.dock = Some(dock);            }        }    }     pub fn set_model(&mut self, language_model: Arc<dyn LanguageModel>) {        let model = language_model.id().0.to_string();        let provider = language_model.provider_id().0.to_string();         match self {            AssistantSettingsContent::Versioned(settings) => match **settings {                VersionedAssistantSettingsContent::V1(ref mut settings) => {                    match provider.as_ref() {                        "zed.dev" => {                            log::warn!("attempted to set zed.dev model on outdated settings");                        }                        "anthropic" => {                            let api_url = match &settings.provider {                                Some(AssistantProviderContentV1::Anthropic { api_url, .. }) => {                                    api_url.clone()                                }                                _ => None,                            };                            settings.provider = Some(AssistantProviderContentV1::Anthropic {                                default_model: AnthropicModel::from_id(&model).ok(),                                api_url,                            });                        }                        "ollama" => {                            let api_url = match &settings.provider {                                Some(AssistantProviderContentV1::Ollama { api_url, .. }) => {                                    api_url.clone()                                }                                _ => None,                            };                            settings.provider = Some(AssistantProviderContentV1::Ollama {                                default_model: Some(ollama::Model::new(&model, None, None)),                                api_url,                            });                        }                        "lmstudio" => {                            let api_url = match &settings.provider {                                Some(AssistantProviderContentV1::LmStudio { api_url, .. }) => {                                    api_url.clone()                                }                                _ => None,                            };                            settings.provider = Some(AssistantProviderContentV1::LmStudio {                                default_model: Some(lmstudio::Model::new(&model, None, None)),                                api_url,                            });                        }                        "openai" => {                            let (api_url, available_models) = match &settings.provider {                                Some(AssistantProviderContentV1::OpenAi {                                    api_url,                                    available_models,                                    ..                                }) => (api_url.clone(), available_models.clone()),                                _ => (None, None),                            };                            settings.provider = Some(AssistantProviderContentV1::OpenAi {                                default_model: OpenAiModel::from_id(&model).ok(),                                api_url,                                available_models,                            });                        }                        "deepseek" => {                            let api_url = match &settings.provider {                                Some(AssistantProviderContentV1::DeepSeek { api_url, .. }) => {                                    api_url.clone()                                }                                _ => None,                            };                            settings.provider = Some(AssistantProviderContentV1::DeepSeek {                                default_model: DeepseekModel::from_id(&model).ok(),                                api_url,                            });                        }                        _ => {}                    }                }                VersionedAssistantSettingsContent::V2(ref mut settings) => {                    settings.default_model = Some(LanguageModelSelection { provider, model });                }            },            AssistantSettingsContent::Legacy(settings) => {                if let Ok(model) = OpenAiModel::from_id(&language_model.id().0) {                    settings.default_open_ai_model = Some(model);                }            }        }    }     pub fn set_inline_assistant_model(&mut self, provider: String, model: String) {        if let AssistantSettingsContent::Versioned(boxed) = self {            if let VersionedAssistantSettingsContent::V2(ref mut settings) = **boxed {                settings.inline_assistant_model = Some(LanguageModelSelection { provider, model });            }        }    }     pub fn set_commit_message_model(&mut self, provider: String, model: String) {        if let AssistantSettingsContent::Versioned(boxed) = self {            if let VersionedAssistantSettingsContent::V2(ref mut settings) = **boxed {                settings.commit_message_model = Some(LanguageModelSelection { provider, model });            }        }    }     pub fn set_thread_summary_model(&mut self, provider: String, model: String) {        if let AssistantSettingsContent::Versioned(boxed) = self {            if let VersionedAssistantSettingsContent::V2(ref mut settings) = **boxed {                settings.thread_summary_model = Some(LanguageModelSelection { provider, model });            }        }    }     pub fn set_always_allow_tool_actions(&mut self, allow: bool) {        let AssistantSettingsContent::Versioned(boxed) = self else {            return;        };         if let VersionedAssistantSettingsContent::V2(ref mut settings) = **boxed {            settings.always_allow_tool_actions = Some(allow);        }    }     pub fn set_profile(&mut self, profile_id: AgentProfileId) {        let AssistantSettingsContent::Versioned(boxed) = self else {            return;        };         if let VersionedAssistantSettingsContent::V2(ref mut settings) = **boxed {            settings.default_profile = Some(profile_id);        }    }     pub fn create_profile(        &mut self,        profile_id: AgentProfileId,        profile: AgentProfile,    ) -> Result<()> {        let AssistantSettingsContent::Versioned(boxed) = self else {            return Ok(());        };         if let VersionedAssistantSettingsContent::V2(ref mut settings) = **boxed {            let profiles = settings.profiles.get_or_insert_default();            if profiles.contains_key(&profile_id) {                bail!("profile with ID '{profile_id}' already exists");            }             profiles.insert(                profile_id,                AgentProfileContent {                    name: profile.name.into(),                    tools: profile.tools,                    enable_all_context_servers: Some(profile.enable_all_context_servers),                    context_servers: profile                        .context_servers                        .into_iter()                        .map(|(server_id, preset)| {                            (                                server_id,                                ContextServerPresetContent {                                    tools: preset.tools,                                },                            )                        })                        .collect(),                },            );        }         Ok(())    }} #[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)]#[serde(tag = "version")]pub enum VersionedAssistantSettingsContent {    #[serde(rename = "1")]    V1(AssistantSettingsContentV1),    #[serde(rename = "2")]    V2(AssistantSettingsContentV2),} impl Default for VersionedAssistantSettingsContent {    fn default() -> Self {        Self::V2(AssistantSettingsContentV2 {            enabled: None,            button: None,            dock: None,            default_width: None,            default_height: None,            default_model: None,            inline_assistant_model: None,            commit_message_model: None,            thread_summary_model: None,            inline_alternatives: None,            enable_experimental_live_diffs: None,            default_profile: None,            profiles: None,            always_allow_tool_actions: None,            notify_when_agent_waiting: None,        })    }} #[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)]pub struct AssistantSettingsContentV2 {    /// Whether the Assistant is enabled.    ///    /// Default: true    enabled: Option<bool>,    /// Whether to show the assistant panel button in the status bar.    ///    /// Default: true    button: Option<bool>,    /// Where to dock the assistant.    ///    /// Default: right    dock: Option<AssistantDockPosition>,    /// Default width in pixels when the assistant is docked to the left or right.    ///    /// Default: 640    default_width: Option<f32>,    /// Default height in pixels when the assistant is docked to the bottom.    ///    /// Default: 320    default_height: Option<f32>,    /// The default model to use when creating new chats and for other features when a specific model is not specified.    default_model: Option<LanguageModelSelection>,    /// Model to use for the inline assistant. Defaults to default_model when not specified.    inline_assistant_model: Option<LanguageModelSelection>,    /// Model to use for generating git commit messages. Defaults to default_model when not specified.    commit_message_model: Option<LanguageModelSelection>,    /// Model to use for generating thread summaries. Defaults to default_model when not specified.    thread_summary_model: Option<LanguageModelSelection>,    /// Additional models with which to generate alternatives when performing inline assists.    inline_alternatives: Option<Vec<LanguageModelSelection>>,    /// Enable experimental live diffs in the assistant panel.    ///    /// Default: false    enable_experimental_live_diffs: Option<bool>,    /// The default profile to use in the Agent.

Lines 1–500 of 795.