Cargo.lock 🔗
@@ -607,6 +607,7 @@ version = "0.1.0"
dependencies = [
"anthropic",
"anyhow",
+ "collections",
"deepseek",
"feature_flags",
"fs",
Marshall Bowers created
This PR adds support for creating new agent profiles via the settings:
```json
{
"assistant": {
"profiles": {
"lua": {
"name": "Lua",
"tools": {
"lua-interpreter": true
}
},
"lua-thinking": {
"name": "Lua + Thinking",
"tools": {
"lua-interpreter": true,
"thinking": true
}
}
}
}
}
```
Release Notes:
- N/A
Cargo.lock | 1
crates/assistant2/src/assistant.rs | 1
crates/assistant2/src/tool_selector.rs | 31 +++++++++---
crates/assistant_settings/Cargo.toml | 1
crates/assistant_settings/src/agent_profile.rs | 0
crates/assistant_settings/src/assistant_settings.rs | 36 +++++++++++++++
6 files changed, 61 insertions(+), 9 deletions(-)
@@ -607,6 +607,7 @@ version = "0.1.0"
dependencies = [
"anthropic",
"anyhow",
+ "collections",
"deepseek",
"feature_flags",
"fs",
@@ -1,5 +1,4 @@
mod active_thread;
-mod agent_profile;
mod assistant_configuration;
mod assistant_model_selector;
mod assistant_panel;
@@ -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<AgentProfile>,
+ profiles: HashMap<Arc<str>, AgentProfile>,
tools: Arc<ToolWorkingSet>,
}
impl ToolSelector {
- pub fn new(tools: Arc<ToolWorkingSet>, _cx: &mut Context<Self>) -> Self {
- Self {
- profiles: vec![AgentProfile::read_only(), AgentProfile::code_writer()],
- tools,
+ pub fn new(tools: Arc<ToolWorkingSet>, cx: &mut Context<Self>) -> 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::<Vec<_>>(),
);
+
+ if profile.tools.contains_key(ScriptingTool::NAME) {
+ tools.enable_scripting_tool();
+ }
}
});
}
@@ -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
@@ -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<LanguageModelSelection>,
pub using_outdated_settings_version: bool,
pub enable_experimental_live_diffs: bool,
+ pub profiles: HashMap<Arc<str>, 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<bool>,
+ #[schemars(skip)]
+ profiles: Option<HashMap<Arc<str>, 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<str>,
+ pub tools: HashMap<Arc<str>, 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,
}),
)
},