assistant2: Allow creating agent profiles via settings (#27216)
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
This commit is contained in:
parent
48b1a43f5e
commit
4b5df2189b
6 changed files with 61 additions and 9 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -607,6 +607,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anthropic",
|
"anthropic",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"collections",
|
||||||
"deepseek",
|
"deepseek",
|
||||||
"feature_flags",
|
"feature_flags",
|
||||||
"fs",
|
"fs",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
mod active_thread;
|
mod active_thread;
|
||||||
mod agent_profile;
|
|
||||||
mod assistant_configuration;
|
mod assistant_configuration;
|
||||||
mod assistant_model_selector;
|
mod assistant_model_selector;
|
||||||
mod assistant_panel;
|
mod assistant_panel;
|
||||||
|
|
|
@ -1,23 +1,34 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use assistant_settings::{AgentProfile, AssistantSettings};
|
||||||
use assistant_tool::{ToolSource, ToolWorkingSet};
|
use assistant_tool::{ToolSource, ToolWorkingSet};
|
||||||
|
use collections::HashMap;
|
||||||
use gpui::Entity;
|
use gpui::Entity;
|
||||||
use scripting_tool::ScriptingTool;
|
use scripting_tool::ScriptingTool;
|
||||||
|
use settings::Settings as _;
|
||||||
use ui::{prelude::*, ContextMenu, PopoverMenu, Tooltip};
|
use ui::{prelude::*, ContextMenu, PopoverMenu, Tooltip};
|
||||||
|
|
||||||
use crate::agent_profile::AgentProfile;
|
|
||||||
|
|
||||||
pub struct ToolSelector {
|
pub struct ToolSelector {
|
||||||
profiles: Vec<AgentProfile>,
|
profiles: HashMap<Arc<str>, AgentProfile>,
|
||||||
tools: Arc<ToolWorkingSet>,
|
tools: Arc<ToolWorkingSet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolSelector {
|
impl ToolSelector {
|
||||||
pub fn new(tools: Arc<ToolWorkingSet>, _cx: &mut Context<Self>) -> Self {
|
pub fn new(tools: Arc<ToolWorkingSet>, cx: &mut Context<Self>) -> Self {
|
||||||
Self {
|
let settings = AssistantSettings::get_global(cx);
|
||||||
profiles: vec![AgentProfile::read_only(), AgentProfile::code_writer()],
|
let mut profiles = settings.profiles.clone();
|
||||||
tools,
|
|
||||||
|
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(
|
fn build_context_menu(
|
||||||
|
@ -31,7 +42,7 @@ impl ToolSelector {
|
||||||
let icon_position = IconPosition::End;
|
let icon_position = IconPosition::End;
|
||||||
|
|
||||||
menu = menu.header("Profiles");
|
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, {
|
menu = menu.toggleable_entry(profile.name.clone(), false, icon_position, None, {
|
||||||
let tools = tool_set.clone();
|
let tools = tool_set.clone();
|
||||||
move |_window, cx| {
|
move |_window, cx| {
|
||||||
|
@ -44,6 +55,10 @@ impl ToolSelector {
|
||||||
.filter_map(|(tool, enabled)| enabled.then(|| tool.clone()))
|
.filter_map(|(tool, enabled)| enabled.then(|| tool.clone()))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if profile.tools.contains_key(ScriptingTool::NAME) {
|
||||||
|
tools.enable_scripting_tool();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ path = "src/assistant_settings.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anthropic = { workspace = true, features = ["schemars"] }
|
anthropic = { workspace = true, features = ["schemars"] }
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
|
collections.workspace = true
|
||||||
feature_flags.workspace = true
|
feature_flags.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
language_model.workspace = true
|
language_model.workspace = true
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
|
mod agent_profile;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use ::open_ai::Model as OpenAiModel;
|
use ::open_ai::Model as OpenAiModel;
|
||||||
use anthropic::Model as AnthropicModel;
|
use anthropic::Model as AnthropicModel;
|
||||||
|
use collections::HashMap;
|
||||||
use deepseek::Model as DeepseekModel;
|
use deepseek::Model as DeepseekModel;
|
||||||
use feature_flags::FeatureFlagAppExt;
|
use feature_flags::FeatureFlagAppExt;
|
||||||
use gpui::{App, Pixels};
|
use gpui::{App, Pixels};
|
||||||
|
@ -12,6 +15,8 @@ use schemars::{schema::Schema, JsonSchema};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{Settings, SettingsSources};
|
use settings::{Settings, SettingsSources};
|
||||||
|
|
||||||
|
pub use crate::agent_profile::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum AssistantDockPosition {
|
pub enum AssistantDockPosition {
|
||||||
|
@ -66,6 +71,7 @@ pub struct AssistantSettings {
|
||||||
pub inline_alternatives: Vec<LanguageModelSelection>,
|
pub inline_alternatives: Vec<LanguageModelSelection>,
|
||||||
pub using_outdated_settings_version: bool,
|
pub using_outdated_settings_version: bool,
|
||||||
pub enable_experimental_live_diffs: bool,
|
pub enable_experimental_live_diffs: bool,
|
||||||
|
pub profiles: HashMap<Arc<str>, AgentProfile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AssistantSettings {
|
impl AssistantSettings {
|
||||||
|
@ -166,6 +172,7 @@ impl AssistantSettingsContent {
|
||||||
editor_model: None,
|
editor_model: None,
|
||||||
inline_alternatives: None,
|
inline_alternatives: None,
|
||||||
enable_experimental_live_diffs: None,
|
enable_experimental_live_diffs: None,
|
||||||
|
profiles: None,
|
||||||
},
|
},
|
||||||
VersionedAssistantSettingsContent::V2(settings) => settings.clone(),
|
VersionedAssistantSettingsContent::V2(settings) => settings.clone(),
|
||||||
},
|
},
|
||||||
|
@ -187,6 +194,7 @@ impl AssistantSettingsContent {
|
||||||
editor_model: None,
|
editor_model: None,
|
||||||
inline_alternatives: None,
|
inline_alternatives: None,
|
||||||
enable_experimental_live_diffs: None,
|
enable_experimental_live_diffs: None,
|
||||||
|
profiles: None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,6 +324,7 @@ impl Default for VersionedAssistantSettingsContent {
|
||||||
editor_model: None,
|
editor_model: None,
|
||||||
inline_alternatives: None,
|
inline_alternatives: None,
|
||||||
enable_experimental_live_diffs: None,
|
enable_experimental_live_diffs: None,
|
||||||
|
profiles: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,6 +361,8 @@ pub struct AssistantSettingsContentV2 {
|
||||||
///
|
///
|
||||||
/// Default: false
|
/// Default: false
|
||||||
enable_experimental_live_diffs: Option<bool>,
|
enable_experimental_live_diffs: Option<bool>,
|
||||||
|
#[schemars(skip)]
|
||||||
|
profiles: Option<HashMap<Arc<str>, AgentProfileContent>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
|
#[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)]
|
#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)]
|
||||||
pub struct AssistantSettingsContentV1 {
|
pub struct AssistantSettingsContentV1 {
|
||||||
/// Whether the Assistant is enabled.
|
/// Whether the Assistant is enabled.
|
||||||
|
@ -482,6 +499,24 @@ impl Settings for AssistantSettings {
|
||||||
&mut settings.enable_experimental_live_diffs,
|
&mut settings.enable_experimental_live_diffs,
|
||||||
value.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)
|
Ok(settings)
|
||||||
|
@ -546,6 +581,7 @@ mod tests {
|
||||||
default_width: None,
|
default_width: None,
|
||||||
default_height: None,
|
default_height: None,
|
||||||
enable_experimental_live_diffs: None,
|
enable_experimental_live_diffs: None,
|
||||||
|
profiles: None,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue