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 de1a822637bf3b31d62bfec0108f274fbe89050a..54828500eaff2c0bcac339352b38ac870d2a0176 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 2688eff33418b203ad1041bdaefbfbb98094c29b..293bc3f7fa248ec421022b67c67f029656c60f33 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 6f05d7811ddfa3e499d798dd6fd87605d0069d48..ed889b0bb942835a4935ce562bebd7f037d5334b 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 6ac1d851f2cb2b62bff9989df0b59a3772abb83b..20f35958fd071b385336edfd15d21f90af7a51ed 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 c2055775035e77936cc310a66c2cf0e35e4e120c..69577ed9347dd66c02c4ea076d4e82d66f92c609 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 8acdaec50f4cfed05668ab34099979f842bb7620..4ea19d1912972c3a29e577cfb2bc90c1b0d6d684 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 719e69256dc11655f586e08c2817353f8fc63fc6..df0ff24f3f8a235696e54c69cb50e1efc1dc4778 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 d8d20c0c6103c634b87fbbf9dfa532ba256c83df..ca0e929525c2d9e843e67806982517ba5f58ccd1 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 577c8b1925fd99c2d5fc88fc4bd38eb81af417e9..1397a2b62f070177748baab205e6030187724675 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 bd243a708952701ee825b48cdfb8702188051a9c..c31b6bcba38cc0f6a5af6bd8966434471ff7e20e 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 556b260335a8c85232da4aaf2b857df2c560309a..4e704be5917c408ecb4fd5c268e202eea82f84b5 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 65d317f1e6cbe94ed4f6e76eb67674b97a24f920..0000000000000000000000000000000000000000 --- 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 73e539473f9bffb52562562cf6f88a34eb863151..275b0a6646ff4fa780cd926f45d240927956b2b7 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 0000000000000000000000000000000000000000..d142541cf3feaf9255f7d1f43a468e9a73191baf --- /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 0000000000000000000000000000000000000000..89e542f750cd3860a0598eff0dc34b56d7336dc4 --- /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 879838552bb7e6125427841b26ff0ace8913c4fb..c98182b24d1cd62e7ff0d20266ec3cbe07619d94 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 ed26446e7429b615aab6906634381727a7f050cd..5b077cf378ce1b3895ac179b81aa4749e0045443 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 48a0be9ef9f3090acdcdf93651867296326b9922..ea94a5ac6b5d262c64f348ae4d82221cd3c4672e 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,