1121 lines · 40.3 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 collections::IndexMap;use deepseek::Model as DeepseekModel;use gpui::{App, Pixels, SharedString};use language_model::LanguageModel;use lmstudio::Model as LmStudioModel;use mistral::Model as MistralModel;use ollama::Model as OllamaModel;use schemars::{JsonSchema, schema::Schema};use serde::{Deserialize, Serialize};use settings::{Settings, SettingsSources}; pub use crate::agent_profile::*; pub fn init(cx: &mut App) {    AgentSettings::register(cx);} #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]#[serde(rename_all = "snake_case")]pub enum AgentDockPosition {    Left,    #[default]    Right,    Bottom,} #[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]#[serde(rename_all = "snake_case")]pub enum DefaultView {    #[default]    Thread,    TextThread,} #[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")]#[schemars(deny_unknown_fields)]pub enum AgentProviderContentV1 {    #[serde(rename = "zed.dev")]    ZedDotDev { default_model: Option<String> },    #[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>,    },    #[serde(rename = "mistral")]    Mistral {        default_model: Option<MistralModel>,        api_url: Option<String>,    },} #[derive(Default, Clone, Debug)]pub struct AgentSettings {    pub enabled: bool,    pub button: bool,    pub dock: AgentDockPosition,    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 default_profile: AgentProfileId,    pub default_view: DefaultView,    pub profiles: IndexMap<AgentProfileId, AgentProfile>,    pub always_allow_tool_actions: bool,    pub notify_when_agent_waiting: NotifyWhenAgentWaiting,    pub play_sound_when_agent_done: bool,    pub stream_edits: bool,    pub single_file_review: bool,    pub model_parameters: Vec<LanguageModelParameters>,    pub preferred_completion_mode: CompletionMode,    pub enable_feedback: bool,} impl AgentSettings {    pub fn temperature_for_model(model: &Arc<dyn LanguageModel>, cx: &App) -> Option<f32> {        let settings = Self::get_global(cx);        settings            .model_parameters            .iter()            .rfind(|setting| setting.matches(model))            .and_then(|m| m.temperature)    }     pub fn set_inline_assistant_model(&mut self, provider: String, model: String) {        self.inline_assistant_model = Some(LanguageModelSelection {            provider: provider.into(),            model,        });    }     pub fn set_commit_message_model(&mut self, provider: String, model: String) {        self.commit_message_model = Some(LanguageModelSelection {            provider: provider.into(),            model,        });    }     pub fn set_thread_summary_model(&mut self, provider: String, model: String) {        self.thread_summary_model = Some(LanguageModelSelection {            provider: provider.into(),            model,        });    }} #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]pub struct LanguageModelParameters {    pub provider: Option<LanguageModelProviderSetting>,    pub model: Option<SharedString>,    pub temperature: Option<f32>,} impl LanguageModelParameters {    pub fn matches(&self, model: &Arc<dyn LanguageModel>) -> bool {        if let Some(provider) = &self.provider {            if provider.0 != model.provider_id().0 {                return false;            }        }        if let Some(setting_model) = &self.model {            if *setting_model != model.id().0 {                return false;            }        }        true    }} /// Agent panel settings#[derive(Clone, Serialize, Deserialize, Debug, Default)]pub struct AgentSettingsContent {    #[serde(flatten)]    pub inner: Option<AgentSettingsContentInner>,} #[derive(Clone, Serialize, Deserialize, Debug)]#[serde(untagged)]pub enum AgentSettingsContentInner {    Versioned(Box<VersionedAgentSettingsContent>),    Legacy(LegacyAgentSettingsContent),} impl AgentSettingsContentInner {    fn for_v2(content: AgentSettingsContentV2) -> Self {        AgentSettingsContentInner::Versioned(Box::new(VersionedAgentSettingsContent::V2(content)))    }} impl JsonSchema for AgentSettingsContent {    fn schema_name() -> String {        VersionedAgentSettingsContent::schema_name()    }     fn json_schema(r#gen: &mut schemars::r#gen::SchemaGenerator) -> Schema {        VersionedAgentSettingsContent::json_schema(r#gen)    }     fn is_referenceable() -> bool {        VersionedAgentSettingsContent::is_referenceable()    }} impl AgentSettingsContent {    pub fn is_version_outdated(&self) -> bool {        match &self.inner {            Some(AgentSettingsContentInner::Versioned(settings)) => match **settings {                VersionedAgentSettingsContent::V1(_) => true,                VersionedAgentSettingsContent::V2(_) => false,            },            Some(AgentSettingsContentInner::Legacy(_)) => true,            None => false,        }    }     fn upgrade(&self) -> AgentSettingsContentV2 {        match &self.inner {            Some(AgentSettingsContentInner::Versioned(settings)) => match **settings {                VersionedAgentSettingsContent::V1(ref settings) => AgentSettingsContentV2 {                    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 {                            AgentProviderContentV1::ZedDotDev { default_model } => default_model                                .map(|model| LanguageModelSelection {                                    provider: "zed.dev".into(),                                    model,                                }),                            AgentProviderContentV1::OpenAi { default_model, .. } => default_model                                .map(|model| LanguageModelSelection {                                    provider: "openai".into(),                                    model: model.id().to_string(),                                }),                            AgentProviderContentV1::Anthropic { default_model, .. } => {                                default_model.map(|model| LanguageModelSelection {                                    provider: "anthropic".into(),                                    model: model.id().to_string(),                                })                            }                            AgentProviderContentV1::Ollama { default_model, .. } => default_model                                .map(|model| LanguageModelSelection {                                    provider: "ollama".into(),                                    model: model.id().to_string(),                                }),                            AgentProviderContentV1::LmStudio { default_model, .. } => default_model                                .map(|model| LanguageModelSelection {                                    provider: "lmstudio".into(),                                    model: model.id().to_string(),                                }),                            AgentProviderContentV1::DeepSeek { default_model, .. } => default_model                                .map(|model| LanguageModelSelection {                                    provider: "deepseek".into(),                                    model: model.id().to_string(),                                }),                            AgentProviderContentV1::Mistral { default_model, .. } => default_model                                .map(|model| LanguageModelSelection {                                    provider: "mistral".into(),                                    model: model.id().to_string(),                                }),                        }),                    inline_assistant_model: None,                    commit_message_model: None,                    thread_summary_model: None,                    inline_alternatives: None,                    default_profile: None,                    default_view: None,                    profiles: None,                    always_allow_tool_actions: None,                    notify_when_agent_waiting: None,                    stream_edits: None,                    single_file_review: None,                    model_parameters: Vec::new(),                    preferred_completion_mode: None,                    enable_feedback: None,                    play_sound_when_agent_done: None,                },                VersionedAgentSettingsContent::V2(ref settings) => settings.clone(),            },            Some(AgentSettingsContentInner::Legacy(settings)) => AgentSettingsContentV2 {                enabled: None,                button: settings.button,                dock: settings.dock,                default_width: settings.default_width,                default_height: settings.default_height,                default_model: Some(LanguageModelSelection {                    provider: "openai".into(),                    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,                default_profile: None,                default_view: None,                profiles: None,                always_allow_tool_actions: None,                notify_when_agent_waiting: None,                stream_edits: None,                single_file_review: None,                model_parameters: Vec::new(),                preferred_completion_mode: None,                enable_feedback: None,                play_sound_when_agent_done: None,            },            None => AgentSettingsContentV2::default(),        }    }     pub fn set_dock(&mut self, dock: AgentDockPosition) {        match &mut self.inner {            Some(AgentSettingsContentInner::Versioned(settings)) => match **settings {                VersionedAgentSettingsContent::V1(ref mut settings) => {                    settings.dock = Some(dock);                }                VersionedAgentSettingsContent::V2(ref mut settings) => {                    settings.dock = Some(dock);                }            },            Some(AgentSettingsContentInner::Legacy(settings)) => {                settings.dock = Some(dock);            }            None => {                self.inner = Some(AgentSettingsContentInner::for_v2(AgentSettingsContentV2 {                    dock: Some(dock),                    ..Default::default()                }))            }        }    }     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 &mut self.inner {            Some(AgentSettingsContentInner::Versioned(settings)) => match **settings {                VersionedAgentSettingsContent::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(AgentProviderContentV1::Anthropic { api_url, .. }) => {                                api_url.clone()                            }                            _ => None,                        };                        settings.provider = Some(AgentProviderContentV1::Anthropic {                            default_model: AnthropicModel::from_id(&model).ok(),                            api_url,                        });                    }                    "ollama" => {                        let api_url = match &settings.provider {                            Some(AgentProviderContentV1::Ollama { api_url, .. }) => api_url.clone(),                            _ => None,                        };                        settings.provider = Some(AgentProviderContentV1::Ollama {                            default_model: Some(ollama::Model::new(                                &model,                                None,                                None,                                Some(language_model.supports_tools()),                                Some(language_model.supports_images()),                                None,                            )),                            api_url,                        });                    }                    "lmstudio" => {                        let api_url = match &settings.provider {                            Some(AgentProviderContentV1::LmStudio { api_url, .. }) => {                                api_url.clone()                            }                            _ => None,                        };                        settings.provider = Some(AgentProviderContentV1::LmStudio {                            default_model: Some(lmstudio::Model::new(&model, None, None, false)),                            api_url,                        });                    }                    "openai" => {                        let (api_url, available_models) = match &settings.provider {                            Some(AgentProviderContentV1::OpenAi {                                api_url,                                available_models,                                ..                            }) => (api_url.clone(), available_models.clone()),                            _ => (None, None),                        };                        settings.provider = Some(AgentProviderContentV1::OpenAi {                            default_model: OpenAiModel::from_id(&model).ok(),                            api_url,                            available_models,                        });                    }                    "deepseek" => {                        let api_url = match &settings.provider {                            Some(AgentProviderContentV1::DeepSeek { api_url, .. }) => {                                api_url.clone()                            }                            _ => None,                        };                        settings.provider = Some(AgentProviderContentV1::DeepSeek {                            default_model: DeepseekModel::from_id(&model).ok(),                            api_url,                        });                    }                    _ => {}                },                VersionedAgentSettingsContent::V2(ref mut settings) => {                    settings.default_model = Some(LanguageModelSelection {                        provider: provider.into(),                        model,                    });                }            },            Some(AgentSettingsContentInner::Legacy(settings)) => {                if let Ok(model) = OpenAiModel::from_id(&language_model.id().0) {                    settings.default_open_ai_model = Some(model);                }            }            None => {                self.inner = Some(AgentSettingsContentInner::for_v2(AgentSettingsContentV2 {                    default_model: Some(LanguageModelSelection {                        provider: provider.into(),                        model,                    }),                    ..Default::default()                }));            }        }    }     pub fn set_inline_assistant_model(&mut self, provider: String, model: String) {        self.v2_setting(|setting| {            setting.inline_assistant_model = Some(LanguageModelSelection {                provider: provider.into(),                model,            });            Ok(())        })        .ok();    }     pub fn set_commit_message_model(&mut self, provider: String, model: String) {        self.v2_setting(|setting| {            setting.commit_message_model = Some(LanguageModelSelection {                provider: provider.into(),                model,            });            Ok(())        })        .ok();    }     pub fn v2_setting(        &mut self,        f: impl FnOnce(&mut AgentSettingsContentV2) -> anyhow::Result<()>,    ) -> anyhow::Result<()> {        match self.inner.get_or_insert_with(|| {            AgentSettingsContentInner::for_v2(AgentSettingsContentV2 {                ..Default::default()            })        }) {            AgentSettingsContentInner::Versioned(boxed) => {                if let VersionedAgentSettingsContent::V2(ref mut settings) = **boxed {                    f(settings)                } else {                    Ok(())                }            }            _ => Ok(()),        }    }     pub fn set_thread_summary_model(&mut self, provider: String, model: String) {        self.v2_setting(|setting| {            setting.thread_summary_model = Some(LanguageModelSelection {                provider: provider.into(),                model,            });            Ok(())        })        .ok();    }     pub fn set_always_allow_tool_actions(&mut self, allow: bool) {        self.v2_setting(|setting| {

Lines 1–500 of 1121.