diff --git a/Cargo.lock b/Cargo.lock index 752feab0b721c1e29fe30863aa5a596f824824f7..e153e4147c68466c70c0428ed4e13b5a87b8eb67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -607,6 +607,7 @@ version = "0.1.0" dependencies = [ "anthropic", "anyhow", + "collections", "deepseek", "feature_flags", "fs", diff --git a/crates/assistant2/src/assistant.rs b/crates/assistant2/src/assistant.rs index d57fe78579987d528a1f910d1ac4e5f623f9fb8c..5224b097cc3594e294963497dddc9cbd03c5563c 100644 --- a/crates/assistant2/src/assistant.rs +++ b/crates/assistant2/src/assistant.rs @@ -1,5 +1,4 @@ mod active_thread; -mod agent_profile; mod assistant_configuration; mod assistant_model_selector; mod assistant_panel; diff --git a/crates/assistant2/src/tool_selector.rs b/crates/assistant2/src/tool_selector.rs index e14e206c6b12726a04e192d247bee72a6c8016e8..43a59e61a86ebea72bb6e712095d89cf950bffe5 100644 --- a/crates/assistant2/src/tool_selector.rs +++ b/crates/assistant2/src/tool_selector.rs @@ -1,23 +1,34 @@ use std::sync::Arc; +use assistant_settings::{AgentProfile, AssistantSettings}; use assistant_tool::{ToolSource, ToolWorkingSet}; +use collections::HashMap; use gpui::Entity; use scripting_tool::ScriptingTool; +use settings::Settings as _; use ui::{prelude::*, ContextMenu, PopoverMenu, Tooltip}; -use crate::agent_profile::AgentProfile; - pub struct ToolSelector { - profiles: Vec, + profiles: HashMap, AgentProfile>, tools: Arc, } impl ToolSelector { - pub fn new(tools: Arc, _cx: &mut Context) -> Self { - Self { - profiles: vec![AgentProfile::read_only(), AgentProfile::code_writer()], - tools, + pub fn new(tools: Arc, cx: &mut Context) -> Self { + let settings = AssistantSettings::get_global(cx); + let mut profiles = settings.profiles.clone(); + + let read_only = AgentProfile::read_only(); + if !profiles.contains_key(read_only.name.as_ref()) { + profiles.insert(read_only.name.clone().into(), read_only); + } + + let code_writer = AgentProfile::code_writer(); + if !profiles.contains_key(code_writer.name.as_ref()) { + profiles.insert(code_writer.name.clone().into(), code_writer); } + + Self { profiles, tools } } fn build_context_menu( @@ -31,7 +42,7 @@ impl ToolSelector { let icon_position = IconPosition::End; menu = menu.header("Profiles"); - for profile in profiles.clone() { + for (_id, profile) in profiles.clone() { menu = menu.toggleable_entry(profile.name.clone(), false, icon_position, None, { let tools = tool_set.clone(); move |_window, cx| { @@ -44,6 +55,10 @@ impl ToolSelector { .filter_map(|(tool, enabled)| enabled.then(|| tool.clone())) .collect::>(), ); + + if profile.tools.contains_key(ScriptingTool::NAME) { + tools.enable_scripting_tool(); + } } }); } diff --git a/crates/assistant_settings/Cargo.toml b/crates/assistant_settings/Cargo.toml index 4398f75ef92a717db81f36188b0ebbd24ecf08e8..96e3f606c0815361b6dde4bbf90d1f1e333f8a2e 100644 --- a/crates/assistant_settings/Cargo.toml +++ b/crates/assistant_settings/Cargo.toml @@ -14,6 +14,7 @@ path = "src/assistant_settings.rs" [dependencies] anthropic = { workspace = true, features = ["schemars"] } anyhow.workspace = true +collections.workspace = true feature_flags.workspace = true gpui.workspace = true language_model.workspace = true diff --git a/crates/assistant2/src/agent_profile.rs b/crates/assistant_settings/src/agent_profile.rs similarity index 100% rename from crates/assistant2/src/agent_profile.rs rename to crates/assistant_settings/src/agent_profile.rs diff --git a/crates/assistant_settings/src/assistant_settings.rs b/crates/assistant_settings/src/assistant_settings.rs index 125c2fbff39cdf200db875a2a8f7ca9f865fc8df..d59e4cbdf230f1af9c585d8a345e9ff4ab5d8a73 100644 --- a/crates/assistant_settings/src/assistant_settings.rs +++ b/crates/assistant_settings/src/assistant_settings.rs @@ -1,7 +1,10 @@ +mod agent_profile; + use std::sync::Arc; use ::open_ai::Model as OpenAiModel; use anthropic::Model as AnthropicModel; +use collections::HashMap; use deepseek::Model as DeepseekModel; use feature_flags::FeatureFlagAppExt; use gpui::{App, Pixels}; @@ -12,6 +15,8 @@ use schemars::{schema::Schema, JsonSchema}; 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 { @@ -66,6 +71,7 @@ pub struct AssistantSettings { pub inline_alternatives: Vec, pub using_outdated_settings_version: bool, pub enable_experimental_live_diffs: bool, + pub profiles: HashMap, AgentProfile>, } impl AssistantSettings { @@ -166,6 +172,7 @@ impl AssistantSettingsContent { editor_model: None, inline_alternatives: None, enable_experimental_live_diffs: None, + profiles: None, }, VersionedAssistantSettingsContent::V2(settings) => settings.clone(), }, @@ -187,6 +194,7 @@ impl AssistantSettingsContent { editor_model: None, inline_alternatives: None, enable_experimental_live_diffs: None, + profiles: None, }, } } @@ -316,6 +324,7 @@ impl Default for VersionedAssistantSettingsContent { editor_model: None, inline_alternatives: None, enable_experimental_live_diffs: None, + profiles: None, }) } } @@ -352,6 +361,8 @@ pub struct AssistantSettingsContentV2 { /// /// Default: false enable_experimental_live_diffs: Option, + #[schemars(skip)] + profiles: Option, AgentProfileContent>>, } #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] @@ -388,6 +399,12 @@ impl Default for LanguageModelSelection { } } +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)] +pub struct AgentProfileContent { + pub name: Arc, + pub tools: HashMap, bool>, +} + #[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)] pub struct AssistantSettingsContentV1 { /// Whether the Assistant is enabled. @@ -482,6 +499,24 @@ impl Settings for AssistantSettings { &mut settings.enable_experimental_live_diffs, value.enable_experimental_live_diffs, ); + merge( + &mut settings.profiles, + value.profiles.map(|profiles| { + profiles + .into_iter() + .map(|(id, profile)| { + ( + id, + AgentProfile { + name: profile.name.into(), + tools: profile.tools, + context_servers: HashMap::default(), + }, + ) + }) + .collect() + }), + ); } Ok(settings) @@ -546,6 +581,7 @@ mod tests { default_width: None, default_height: None, enable_experimental_live_diffs: None, + profiles: None, }), ) },