From e215ca1d9996b7fd600c9b5d1eef1b7400e8fe4b Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 15 Jan 2025 13:52:54 -0500 Subject: [PATCH] Dedupe `AssistantSettings` (#23190) This PR dedupes the `AssistantSettings` so we can use the same settings for both Assistant1 and Assistant2. We originally forked them so we could change the Assistant2 settings freely, but given our rollout strategy for the new Assistant, I don't think that makes sense. This also fixes the issue where the JSON language server would show a "Matches multiple schemas when only one must validate" warning in `settings.json`. Closes #23171. Release Notes: - Fixed the "Matches multiple schemas when only one must validate" warning for the `assistant` setting. --- Cargo.lock | 33 +- Cargo.toml | 2 + crates/assistant/Cargo.toml | 4 +- crates/assistant/src/assistant.rs | 1 - crates/assistant/src/assistant_panel.rs | 2 +- crates/assistant/src/inline_assistant.rs | 7 +- .../src/terminal_inline_assistant.rs | 2 +- crates/assistant2/Cargo.toml | 7 +- crates/assistant2/src/assistant.rs | 3 +- .../src/assistant_model_selector.rs | 3 +- crates/assistant2/src/assistant_panel.rs | 2 +- crates/assistant2/src/assistant_settings.rs | 526 ------------------ crates/assistant2/src/inline_assistant.rs | 27 +- crates/assistant_settings/Cargo.toml | 33 ++ crates/assistant_settings/LICENSE-GPL | 1 + .../src/assistant_settings.rs | 3 +- crates/zed/Cargo.toml | 1 + crates/zed/src/zed/quick_action_bar.rs | 2 +- 18 files changed, 91 insertions(+), 568 deletions(-) delete mode 100644 crates/assistant2/src/assistant_settings.rs create mode 100644 crates/assistant_settings/Cargo.toml create mode 120000 crates/assistant_settings/LICENSE-GPL rename crates/{assistant => assistant_settings}/src/assistant_settings.rs (99%) diff --git a/Cargo.lock b/Cargo.lock index de1a822637..54828500ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -372,9 +372,9 @@ dependencies = [ name = "assistant" version = "0.1.0" dependencies = [ - "anthropic", "anyhow", "assets", + "assistant_settings", "assistant_slash_command", "assistant_tool", "async-watch", @@ -406,13 +406,11 @@ dependencies = [ "language_model_selector", "language_models", "languages", - "lmstudio", "log", "lsp", "markdown", "menu", "multi_buffer", - "ollama", "open_ai", "ordered-float 2.10.1", "parking_lot", @@ -457,9 +455,9 @@ dependencies = [ name = "assistant2" version = "0.1.0" dependencies = [ - "anthropic", "anyhow", "assets", + "assistant_settings", "assistant_tool", "async-watch", "chrono", @@ -485,14 +483,11 @@ dependencies = [ "language_model", "language_model_selector", "language_models", - "lmstudio", "log", "lsp", "markdown", "menu", "multi_buffer", - "ollama", - "open_ai", "ordered-float 2.10.1", "parking_lot", "paths", @@ -501,10 +496,8 @@ dependencies = [ "proto", "rand 0.8.5", "rope", - "schemars", "serde", "serde_json", - "serde_json_lenient", "settings", "similar", "smol", @@ -523,6 +516,27 @@ dependencies = [ "zed_actions", ] +[[package]] +name = "assistant_settings" +version = "0.1.0" +dependencies = [ + "anthropic", + "anyhow", + "feature_flags", + "fs", + "gpui", + "language_model", + "lmstudio", + "log", + "ollama", + "open_ai", + "paths", + "schemars", + "serde", + "serde_json_lenient", + "settings", +] + [[package]] name = "assistant_slash_command" version = "0.1.0" @@ -16110,6 +16124,7 @@ dependencies = [ "assets", "assistant", "assistant2", + "assistant_settings", "assistant_tools", "async-watch", "audio", diff --git a/Cargo.toml b/Cargo.toml index 2688eff334..293bc3f7fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "crates/assets", "crates/assistant", "crates/assistant2", + "crates/assistant_settings", "crates/assistant_slash_command", "crates/assistant_tool", "crates/assistant_tools", @@ -194,6 +195,7 @@ anthropic = { path = "crates/anthropic" } assets = { path = "crates/assets" } assistant = { path = "crates/assistant" } assistant2 = { path = "crates/assistant2" } +assistant_settings = { path = "crates/assistant_settings" } assistant_slash_command = { path = "crates/assistant_slash_command" } assistant_tool = { path = "crates/assistant_tool" } assistant_tools = { path = "crates/assistant_tools" } diff --git a/crates/assistant/Cargo.toml b/crates/assistant/Cargo.toml index 6f05d7811d..ed889b0bb9 100644 --- a/crates/assistant/Cargo.toml +++ b/crates/assistant/Cargo.toml @@ -21,9 +21,9 @@ test-support = [ ] [dependencies] -anthropic = { workspace = true, features = ["schemars"] } anyhow.workspace = true assets.workspace = true +assistant_settings.workspace = true assistant_slash_command.workspace = true assistant_tool.workspace = true async-watch.workspace = true @@ -52,13 +52,11 @@ language.workspace = true language_model.workspace = true language_model_selector.workspace = true language_models.workspace = true -lmstudio = { workspace = true, features = ["schemars"] } log.workspace = true lsp.workspace = true markdown.workspace = true menu.workspace = true multi_buffer.workspace = true -ollama = { workspace = true, features = ["schemars"] } open_ai = { workspace = true, features = ["schemars"] } ordered-float.workspace = true parking_lot.workspace = true diff --git a/crates/assistant/src/assistant.rs b/crates/assistant/src/assistant.rs index 6ac1d851f2..20f35958fd 100644 --- a/crates/assistant/src/assistant.rs +++ b/crates/assistant/src/assistant.rs @@ -1,7 +1,6 @@ #![cfg_attr(target_os = "windows", allow(unused, dead_code))] pub mod assistant_panel; -pub mod assistant_settings; mod context; pub mod context_store; mod inline_assistant; diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index c205577503..69577ed934 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -1,7 +1,6 @@ use crate::slash_command::file_command::codeblock_fence_for_path; use crate::slash_command_working_set::SlashCommandWorkingSet; use crate::{ - assistant_settings::{AssistantDockPosition, AssistantSettings}, humanize_token_count, prompt_library::open_prompt_library, prompts::PromptBuilder, @@ -21,6 +20,7 @@ use crate::{ ToggleModelSelector, }; use anyhow::Result; +use assistant_settings::{AssistantDockPosition, AssistantSettings}; use assistant_slash_command::{SlashCommand, SlashCommandOutputSection}; use assistant_tool::ToolWorkingSet; use client::{proto, zed_urls, Client, Status}; diff --git a/crates/assistant/src/inline_assistant.rs b/crates/assistant/src/inline_assistant.rs index 8acdaec50f..4ea19d1912 100644 --- a/crates/assistant/src/inline_assistant.rs +++ b/crates/assistant/src/inline_assistant.rs @@ -1,9 +1,10 @@ use crate::{ - assistant_settings::AssistantSettings, humanize_token_count, prompts::PromptBuilder, - AssistantPanel, AssistantPanelEvent, CharOperation, CycleNextInlineAssist, - CyclePreviousInlineAssist, LineDiff, LineOperation, RequestType, StreamingDiff, + humanize_token_count, prompts::PromptBuilder, AssistantPanel, AssistantPanelEvent, + CharOperation, CycleNextInlineAssist, CyclePreviousInlineAssist, LineDiff, LineOperation, + RequestType, StreamingDiff, }; use anyhow::{anyhow, Context as _, Result}; +use assistant_settings::AssistantSettings; use client::{telemetry::Telemetry, ErrorExt}; use collections::{hash_map, HashMap, HashSet, VecDeque}; use editor::{ diff --git a/crates/assistant/src/terminal_inline_assistant.rs b/crates/assistant/src/terminal_inline_assistant.rs index 719e69256d..df0ff24f3f 100644 --- a/crates/assistant/src/terminal_inline_assistant.rs +++ b/crates/assistant/src/terminal_inline_assistant.rs @@ -1,9 +1,9 @@ -use crate::assistant_settings::AssistantSettings; use crate::{ humanize_token_count, prompts::PromptBuilder, AssistantPanel, AssistantPanelEvent, RequestType, DEFAULT_CONTEXT_LINES, }; use anyhow::{Context as _, Result}; +use assistant_settings::AssistantSettings; use client::telemetry::Telemetry; use collections::{HashMap, VecDeque}; use editor::{ diff --git a/crates/assistant2/Cargo.toml b/crates/assistant2/Cargo.toml index d8d20c0c61..ca0e929525 100644 --- a/crates/assistant2/Cargo.toml +++ b/crates/assistant2/Cargo.toml @@ -13,9 +13,9 @@ path = "src/assistant.rs" doctest = false [dependencies] -anthropic = { workspace = true, features = ["schemars"] } anyhow.workspace = true assets.workspace = true +assistant_settings.workspace = true assistant_tool.workspace = true async-watch.workspace = true chrono.workspace = true @@ -45,9 +45,6 @@ lsp.workspace = true markdown.workspace = true menu.workspace = true multi_buffer.workspace = true -ollama = { workspace = true, features = ["schemars"] } -lmstudio = { workspace = true, features = ["schemars"] } -open_ai = { workspace = true, features = ["schemars"] } ordered-float.workspace = true parking_lot.workspace = true paths.workspace = true @@ -55,10 +52,8 @@ picker.workspace = true project.workspace = true proto.workspace = true rope.workspace = true -schemars.workspace = true serde.workspace = true serde_json.workspace = true -serde_json_lenient.workspace = true settings.workspace = true similar.workspace = true smol.workspace = true diff --git a/crates/assistant2/src/assistant.rs b/crates/assistant2/src/assistant.rs index 577c8b1925..1397a2b62f 100644 --- a/crates/assistant2/src/assistant.rs +++ b/crates/assistant2/src/assistant.rs @@ -1,7 +1,6 @@ mod active_thread; mod assistant_model_selector; mod assistant_panel; -mod assistant_settings; mod buffer_codegen; mod context; mod context_picker; @@ -21,6 +20,7 @@ mod ui; use std::sync::Arc; +use assistant_settings::AssistantSettings; use client::Client; use command_palette_hooks::CommandPaletteFilter; use feature_flags::{Assistant2FeatureFlag, FeatureFlagAppExt}; @@ -31,7 +31,6 @@ use settings::Settings as _; use util::ResultExt; pub use crate::assistant_panel::AssistantPanel; -use crate::assistant_settings::AssistantSettings; pub use crate::inline_assistant::InlineAssistant; actions!( diff --git a/crates/assistant2/src/assistant_model_selector.rs b/crates/assistant2/src/assistant_model_selector.rs index bd243a7089..c31b6bcba3 100644 --- a/crates/assistant2/src/assistant_model_selector.rs +++ b/crates/assistant2/src/assistant_model_selector.rs @@ -1,3 +1,4 @@ +use assistant_settings::AssistantSettings; use fs::Fs; use gpui::{FocusHandle, View}; use language_model::LanguageModelRegistry; @@ -6,7 +7,7 @@ use settings::update_settings_file; use std::sync::Arc; use ui::{prelude::*, ButtonLike, PopoverMenuHandle, Tooltip}; -use crate::{assistant_settings::AssistantSettings, ToggleModelSelector}; +use crate::ToggleModelSelector; pub struct AssistantModelSelector { selector: View, diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 556b260335..4e704be591 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use anyhow::Result; +use assistant_settings::{AssistantDockPosition, AssistantSettings}; use assistant_tool::ToolWorkingSet; use client::zed_urls; use fs::Fs; @@ -17,7 +18,6 @@ use workspace::dock::{DockPosition, Panel, PanelEvent}; use workspace::Workspace; use crate::active_thread::ActiveThread; -use crate::assistant_settings::{AssistantDockPosition, AssistantSettings}; use crate::message_editor::MessageEditor; use crate::thread::{Thread, ThreadError, ThreadId}; use crate::thread_history::{PastThread, ThreadHistory}; diff --git a/crates/assistant2/src/assistant_settings.rs b/crates/assistant2/src/assistant_settings.rs deleted file mode 100644 index 65d317f1e6..0000000000 --- a/crates/assistant2/src/assistant_settings.rs +++ /dev/null @@ -1,526 +0,0 @@ -use std::sync::Arc; - -use ::open_ai::Model as OpenAiModel; -use anthropic::Model as AnthropicModel; -use gpui::Pixels; -use language_model::{CloudModel, LanguageModel}; -use lmstudio::Model as LmStudioModel; -use ollama::Model as OllamaModel; -use schemars::{schema::Schema, JsonSchema}; -use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsSources}; - -#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum AssistantDockPosition { - Left, - #[default] - Right, - Bottom, -} - -#[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 }, - #[serde(rename = "openai")] - OpenAi { - default_model: Option, - api_url: Option, - available_models: Option>, - }, - #[serde(rename = "anthropic")] - Anthropic { - default_model: Option, - api_url: Option, - }, - #[serde(rename = "ollama")] - Ollama { - default_model: Option, - api_url: Option, - }, - #[serde(rename = "lmstudio")] - LmStudio { - default_model: Option, - api_url: Option, - }, -} - -#[derive(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_alternatives: Vec, - pub using_outdated_settings_version: bool, - pub enable_experimental_live_diffs: bool, -} - -/// Assistant panel settings -#[derive(Clone, Serialize, Deserialize, Debug)] -#[serde(untagged)] -pub enum AssistantSettingsContent { - Versioned(VersionedAssistantSettingsContent), - Legacy(LegacyAssistantSettingsContent), -} - -impl JsonSchema for AssistantSettingsContent { - fn schema_name() -> String { - VersionedAssistantSettingsContent::schema_name() - } - - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> Schema { - VersionedAssistantSettingsContent::json_schema(gen) - } - - fn is_referenceable() -> bool { - VersionedAssistantSettingsContent::is_referenceable() - } -} - -impl Default for AssistantSettingsContent { - fn default() -> Self { - Self::Versioned(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(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(), - }) - } - }), - inline_alternatives: None, - enable_experimental_live_diffs: None, - }, - VersionedAssistantSettingsContent::V2(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_alternatives: None, - enable_experimental_live_diffs: None, - }, - } - } - - pub fn set_dock(&mut self, dock: AssistantDockPosition) { - match self { - AssistantSettingsContent::Versioned(settings) => match settings { - VersionedAssistantSettingsContent::V1(settings) => { - settings.dock = Some(dock); - } - VersionedAssistantSettingsContent::V2(settings) => { - settings.dock = Some(dock); - } - }, - AssistantSettingsContent::Legacy(settings) => { - settings.dock = Some(dock); - } - } - } - - pub fn set_model(&mut self, language_model: Arc) { - 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(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, - }); - } - _ => {} - }, - VersionedAssistantSettingsContent::V2(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); - } - } - } - } -} - -#[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_alternatives: None, - enable_experimental_live_diffs: None, - }) - } -} - -#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)] -pub struct AssistantSettingsContentV2 { - /// Whether the Assistant is enabled. - /// - /// Default: true - enabled: Option, - /// Whether to show the assistant panel button in the status bar. - /// - /// Default: true - button: Option, - /// Where to dock the assistant. - /// - /// Default: right - dock: Option, - /// Default width in pixels when the assistant is docked to the left or right. - /// - /// Default: 640 - default_width: Option, - /// Default height in pixels when the assistant is docked to the bottom. - /// - /// Default: 320 - default_height: Option, - /// The default model to use when creating new chats. - default_model: Option, - /// Additional models with which to generate alternatives when performing inline assists. - inline_alternatives: Option>, - /// Enable experimental live diffs in the assistant panel. - /// - /// Default: false - enable_experimental_live_diffs: Option, -} - -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] -pub struct LanguageModelSelection { - #[schemars(schema_with = "providers_schema")] - pub provider: String, - pub model: String, -} - -fn providers_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - schemars::schema::SchemaObject { - enum_values: Some(vec![ - "anthropic".into(), - "google".into(), - "lmstudio".into(), - "ollama".into(), - "openai".into(), - "zed.dev".into(), - "copilot_chat".into(), - ]), - ..Default::default() - } - .into() -} - -impl Default for LanguageModelSelection { - fn default() -> Self { - Self { - provider: "openai".to_string(), - model: "gpt-4".to_string(), - } - } -} - -#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)] -pub struct AssistantSettingsContentV1 { - /// Whether the Assistant is enabled. - /// - /// Default: true - enabled: Option, - /// Whether to show the assistant panel button in the status bar. - /// - /// Default: true - button: Option, - /// Where to dock the assistant. - /// - /// Default: right - dock: Option, - /// Default width in pixels when the assistant is docked to the left or right. - /// - /// Default: 640 - default_width: Option, - /// Default height in pixels when the assistant is docked to the bottom. - /// - /// Default: 320 - default_height: Option, - /// The provider of the assistant service. - /// - /// This can be "openai", "anthropic", "ollama", "zed.dev" - /// each with their respective default models and configurations. - provider: Option, -} - -#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)] -pub struct LegacyAssistantSettingsContent { - /// Whether to show the assistant panel button in the status bar. - /// - /// Default: true - pub button: Option, - /// Where to dock the assistant. - /// - /// Default: right - pub dock: Option, - /// Default width in pixels when the assistant is docked to the left or right. - /// - /// Default: 640 - pub default_width: Option, - /// Default height in pixels when the assistant is docked to the bottom. - /// - /// Default: 320 - pub default_height: Option, - /// The default OpenAI model to use when creating new chats. - /// - /// Default: gpt-4-1106-preview - pub default_open_ai_model: Option, - /// OpenAI API base URL to use when creating new chats. - /// - /// Default: https://api.openai.com/v1 - pub openai_api_url: Option, -} - -impl Settings for AssistantSettings { - const KEY: Option<&'static str> = Some("assistant"); - - const PRESERVED_KEYS: Option<&'static [&'static str]> = Some(&["version"]); - - type FileContent = AssistantSettingsContent; - - fn load( - sources: SettingsSources, - _: &mut gpui::AppContext, - ) -> anyhow::Result { - let mut settings = AssistantSettings::default(); - - for value in sources.defaults_and_customizations() { - if value.is_version_outdated() { - settings.using_outdated_settings_version = true; - } - - let value = value.upgrade(); - merge(&mut settings.enabled, value.enabled); - merge(&mut settings.button, value.button); - merge(&mut settings.dock, value.dock); - merge( - &mut settings.default_width, - value.default_width.map(Into::into), - ); - merge( - &mut settings.default_height, - value.default_height.map(Into::into), - ); - merge(&mut settings.default_model, value.default_model); - merge(&mut settings.inline_alternatives, value.inline_alternatives); - merge( - &mut settings.enable_experimental_live_diffs, - value.enable_experimental_live_diffs, - ); - } - - Ok(settings) - } -} - -fn merge(target: &mut T, value: Option) { - if let Some(value) = value { - *target = value; - } -} - -#[cfg(test)] -mod tests { - use fs::Fs; - use gpui::{ReadGlobal, TestAppContext}; - - use super::*; - - #[gpui::test] - async fn test_deserialize_assistant_settings_with_version(cx: &mut TestAppContext) { - let fs = fs::FakeFs::new(cx.executor().clone()); - fs.create_dir(paths::settings_file().parent().unwrap()) - .await - .unwrap(); - - cx.update(|cx| { - let test_settings = settings::SettingsStore::test(cx); - cx.set_global(test_settings); - AssistantSettings::register(cx); - }); - - cx.update(|cx| { - assert!(!AssistantSettings::get_global(cx).using_outdated_settings_version); - assert_eq!( - AssistantSettings::get_global(cx).default_model, - LanguageModelSelection { - provider: "zed.dev".into(), - model: "claude-3-5-sonnet".into(), - } - ); - }); - - cx.update(|cx| { - settings::SettingsStore::global(cx).update_settings_file::( - fs.clone(), - |settings, _| { - *settings = AssistantSettingsContent::Versioned( - VersionedAssistantSettingsContent::V2(AssistantSettingsContentV2 { - default_model: Some(LanguageModelSelection { - provider: "test-provider".into(), - model: "gpt-99".into(), - }), - inline_alternatives: None, - enabled: None, - button: None, - dock: None, - default_width: None, - default_height: None, - enable_experimental_live_diffs: None, - }), - ) - }, - ); - }); - - cx.run_until_parked(); - - let raw_settings_value = fs.load(paths::settings_file()).await.unwrap(); - assert!(raw_settings_value.contains(r#""version": "2""#)); - - #[derive(Debug, Deserialize)] - struct AssistantSettingsTest { - assistant: AssistantSettingsContent, - } - - let assistant_settings: AssistantSettingsTest = - serde_json_lenient::from_str(&raw_settings_value).unwrap(); - - assert!(!assistant_settings.assistant.is_version_outdated()); - } -} diff --git a/crates/assistant2/src/inline_assistant.rs b/crates/assistant2/src/inline_assistant.rs index 73e539473f..275b0a6646 100644 --- a/crates/assistant2/src/inline_assistant.rs +++ b/crates/assistant2/src/inline_assistant.rs @@ -1,13 +1,11 @@ -use crate::buffer_codegen::{BufferCodegen, CodegenAlternative, CodegenEvent}; -use crate::context_store::ContextStore; -use crate::inline_prompt_editor::{CodegenStatus, InlineAssistId, PromptEditor, PromptEditorEvent}; -use crate::thread_store::ThreadStore; -use crate::AssistantPanel; -use crate::{ - assistant_settings::AssistantSettings, prompts::PromptBuilder, - terminal_inline_assistant::TerminalInlineAssistant, -}; +use std::cmp; +use std::mem; +use std::ops::Range; +use std::rc::Rc; +use std::sync::Arc; + use anyhow::{Context as _, Result}; +use assistant_settings::AssistantSettings; use client::telemetry::Telemetry; use collections::{hash_map, HashMap, HashSet, VecDeque}; use editor::{ @@ -21,8 +19,6 @@ use editor::{ }; use feature_flags::{Assistant2FeatureFlag, FeatureFlagViewExt as _}; use fs::Fs; -use util::ResultExt; - use gpui::{ point, AppContext, FocusableView, Global, HighlightStyle, Model, Subscription, Task, UpdateGlobal, View, ViewContext, WeakModel, WeakView, WindowContext, @@ -34,15 +30,22 @@ use multi_buffer::MultiBufferRow; use parking_lot::Mutex; use project::{CodeAction, ProjectTransaction}; use settings::{Settings, SettingsStore}; -use std::{cmp, mem, ops::Range, rc::Rc, sync::Arc}; use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase}; use terminal_view::{terminal_panel::TerminalPanel, TerminalView}; use text::{OffsetRangeExt, ToPoint as _}; use ui::prelude::*; use util::RangeExt; +use util::ResultExt; use workspace::{dock::Panel, ShowConfiguration}; use workspace::{notifications::NotificationId, ItemHandle, Toast, Workspace}; +use crate::buffer_codegen::{BufferCodegen, CodegenAlternative, CodegenEvent}; +use crate::context_store::ContextStore; +use crate::inline_prompt_editor::{CodegenStatus, InlineAssistId, PromptEditor, PromptEditorEvent}; +use crate::thread_store::ThreadStore; +use crate::AssistantPanel; +use crate::{prompts::PromptBuilder, terminal_inline_assistant::TerminalInlineAssistant}; + pub fn init( fs: Arc, prompt_builder: Arc, diff --git a/crates/assistant_settings/Cargo.toml b/crates/assistant_settings/Cargo.toml new file mode 100644 index 0000000000..d142541cf3 --- /dev/null +++ b/crates/assistant_settings/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "assistant_settings" +version = "0.1.0" +edition = "2021" +publish = false +license = "GPL-3.0-or-later" + +[lints] +workspace = true + +[lib] +path = "src/assistant_settings.rs" + +[dependencies] +anthropic = { workspace = true, features = ["schemars"] } +anyhow.workspace = true +feature_flags.workspace = true +gpui.workspace = true +language_model.workspace = true +lmstudio = { workspace = true, features = ["schemars"] } +log.workspace = true +ollama = { workspace = true, features = ["schemars"] } +open_ai = { workspace = true, features = ["schemars"] } +schemars.workspace = true +serde.workspace = true +settings.workspace = true + +[dev-dependencies] +fs.workspace = true +gpui = { workspace = true, features = ["test-support"] } +paths.workspace = true +serde_json_lenient.workspace = true +settings = { workspace = true, features = ["test-support"] } diff --git a/crates/assistant_settings/LICENSE-GPL b/crates/assistant_settings/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/assistant_settings/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/crates/assistant/src/assistant_settings.rs b/crates/assistant_settings/src/assistant_settings.rs similarity index 99% rename from crates/assistant/src/assistant_settings.rs rename to crates/assistant_settings/src/assistant_settings.rs index 879838552b..c98182b24d 100644 --- a/crates/assistant/src/assistant_settings.rs +++ b/crates/assistant_settings/src/assistant_settings.rs @@ -41,6 +41,7 @@ pub enum AssistantProviderContentV1 { default_model: Option, api_url: Option, }, + #[serde(rename = "lmstudio")] LmStudio { default_model: Option, api_url: Option, @@ -335,8 +336,8 @@ fn providers_schema(_: &mut schemars::gen::SchemaGenerator) -> schemars::schema: enum_values: Some(vec![ "anthropic".into(), "google".into(), - "ollama".into(), "lmstudio".into(), + "ollama".into(), "openai".into(), "zed.dev".into(), "copilot_chat".into(), diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index ed26446e74..5b077cf378 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -20,6 +20,7 @@ anyhow.workspace = true assets.workspace = true assistant.workspace = true assistant2.workspace = true +assistant_settings.workspace = true assistant_tools.workspace = true async-watch.workspace = true audio.workspace = true diff --git a/crates/zed/src/zed/quick_action_bar.rs b/crates/zed/src/zed/quick_action_bar.rs index 48a0be9ef9..ea94a5ac6b 100644 --- a/crates/zed/src/zed/quick_action_bar.rs +++ b/crates/zed/src/zed/quick_action_bar.rs @@ -1,8 +1,8 @@ mod markdown_preview; mod repl_menu; -use assistant::assistant_settings::AssistantSettings; use assistant::AssistantPanel; +use assistant_settings::AssistantSettings; use editor::actions::{ AddSelectionAbove, AddSelectionBelow, DuplicateLineDown, GoToDiagnostic, GoToHunk, GoToPrevDiagnostic, GoToPrevHunk, MoveLineDown, MoveLineUp, SelectAll, SelectLargerSyntaxNode,