agent: Add newtype for profile IDs (#27939)

This PR adds an `AgentProfileId` newtype for profile IDs that we can use
instead of `Arc<str>` everywhere.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2025-04-02 13:12:52 -04:00 committed by GitHub
parent b2904e5d9f
commit 646f65511c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 59 additions and 27 deletions

View file

@ -23,7 +23,7 @@ mod ui;
use std::sync::Arc; use std::sync::Arc;
use assistant_settings::AssistantSettings; use assistant_settings::{AgentProfileId, AssistantSettings};
use client::Client; use client::Client;
use command_palette_hooks::CommandPaletteFilter; use command_palette_hooks::CommandPaletteFilter;
use feature_flags::{Assistant2FeatureFlag, FeatureFlagAppExt}; use feature_flags::{Assistant2FeatureFlag, FeatureFlagAppExt};
@ -82,11 +82,11 @@ pub struct NewThread {
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)] #[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema)]
pub struct ManageProfiles { pub struct ManageProfiles {
#[serde(default)] #[serde(default)]
pub customize_tools: Option<Arc<str>>, pub customize_tools: Option<AgentProfileId>,
} }
impl ManageProfiles { impl ManageProfiles {
pub fn customize_tools(profile_id: Arc<str>) -> Self { pub fn customize_tools(profile_id: AgentProfileId) -> Self {
Self { Self {
customize_tools: Some(profile_id), customize_tools: Some(profile_id),
} }

View file

@ -2,7 +2,7 @@ mod profile_modal_header;
use std::sync::Arc; use std::sync::Arc;
use assistant_settings::{AgentProfile, AssistantSettings}; use assistant_settings::{AgentProfile, AgentProfileId, AssistantSettings};
use assistant_tool::ToolWorkingSet; use assistant_tool::ToolWorkingSet;
use convert_case::{Case, Casing as _}; use convert_case::{Case, Casing as _};
use editor::Editor; use editor::Editor;
@ -27,7 +27,7 @@ enum Mode {
NewProfile(NewProfileMode), NewProfile(NewProfileMode),
ViewProfile(ViewProfileMode), ViewProfile(ViewProfileMode),
ConfigureTools { ConfigureTools {
profile_id: Arc<str>, profile_id: AgentProfileId,
tool_picker: Entity<ToolPicker>, tool_picker: Entity<ToolPicker>,
_subscription: Subscription, _subscription: Subscription,
}, },
@ -58,7 +58,7 @@ impl Mode {
#[derive(Clone)] #[derive(Clone)]
struct ProfileEntry { struct ProfileEntry {
pub id: Arc<str>, pub id: AgentProfileId,
pub name: SharedString, pub name: SharedString,
pub navigation: NavigableEntry, pub navigation: NavigableEntry,
} }
@ -71,7 +71,7 @@ pub struct ChooseProfileMode {
#[derive(Clone)] #[derive(Clone)]
pub struct ViewProfileMode { pub struct ViewProfileMode {
profile_id: Arc<str>, profile_id: AgentProfileId,
fork_profile: NavigableEntry, fork_profile: NavigableEntry,
configure_tools: NavigableEntry, configure_tools: NavigableEntry,
} }
@ -79,7 +79,7 @@ pub struct ViewProfileMode {
#[derive(Clone)] #[derive(Clone)]
pub struct NewProfileMode { pub struct NewProfileMode {
name_editor: Entity<Editor>, name_editor: Entity<Editor>,
base_profile_id: Option<Arc<str>>, base_profile_id: Option<AgentProfileId>,
} }
pub struct ManageProfilesModal { pub struct ManageProfilesModal {
@ -140,7 +140,7 @@ impl ManageProfilesModal {
fn new_profile( fn new_profile(
&mut self, &mut self,
base_profile_id: Option<Arc<str>>, base_profile_id: Option<AgentProfileId>,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
@ -158,7 +158,7 @@ impl ManageProfilesModal {
pub fn view_profile( pub fn view_profile(
&mut self, &mut self,
profile_id: Arc<str>, profile_id: AgentProfileId,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
@ -172,7 +172,7 @@ impl ManageProfilesModal {
fn configure_tools( fn configure_tools(
&mut self, &mut self,
profile_id: Arc<str>, profile_id: AgentProfileId,
window: &mut Window, window: &mut Window,
cx: &mut Context<Self>, cx: &mut Context<Self>,
) { ) {
@ -219,7 +219,7 @@ impl ManageProfilesModal {
.and_then(|profile_id| settings.profiles.get(profile_id).cloned()); .and_then(|profile_id| settings.profiles.get(profile_id).cloned());
let name = mode.name_editor.read(cx).text(cx); let name = mode.name_editor.read(cx).text(cx);
let profile_id: Arc<str> = name.to_case(Case::Kebab).into(); let profile_id = AgentProfileId(name.to_case(Case::Kebab).into());
let profile = AgentProfile { let profile = AgentProfile {
name: name.into(), name: name.into(),
@ -261,7 +261,12 @@ impl ManageProfilesModal {
} }
} }
fn create_profile(&self, profile_id: Arc<str>, profile: AgentProfile, cx: &mut Context<Self>) { fn create_profile(
&self,
profile_id: AgentProfileId,
profile: AgentProfile,
cx: &mut Context<Self>,
) {
update_settings_file::<AssistantSettings>(self.fs.clone(), cx, { update_settings_file::<AssistantSettings>(self.fs.clone(), cx, {
move |settings, _cx| { move |settings, _cx| {
settings.create_profile(profile_id, profile).log_err(); settings.create_profile(profile_id, profile).log_err();

View file

@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use assistant_settings::{ use assistant_settings::{
AgentProfile, AgentProfileContent, AssistantSettings, AssistantSettingsContent, AgentProfile, AgentProfileContent, AgentProfileId, AssistantSettings, AssistantSettingsContent,
ContextServerPresetContent, VersionedAssistantSettingsContent, ContextServerPresetContent, VersionedAssistantSettingsContent,
}; };
use assistant_tool::{ToolSource, ToolWorkingSet}; use assistant_tool::{ToolSource, ToolWorkingSet};
@ -51,7 +51,7 @@ pub struct ToolPickerDelegate {
thread_store: WeakEntity<ThreadStore>, thread_store: WeakEntity<ThreadStore>,
fs: Arc<dyn Fs>, fs: Arc<dyn Fs>,
tools: Vec<ToolEntry>, tools: Vec<ToolEntry>,
profile_id: Arc<str>, profile_id: AgentProfileId,
profile: AgentProfile, profile: AgentProfile,
matches: Vec<StringMatch>, matches: Vec<StringMatch>,
selected_index: usize, selected_index: usize,
@ -62,7 +62,7 @@ impl ToolPickerDelegate {
fs: Arc<dyn Fs>, fs: Arc<dyn Fs>,
tool_set: Arc<ToolWorkingSet>, tool_set: Arc<ToolWorkingSet>,
thread_store: WeakEntity<ThreadStore>, thread_store: WeakEntity<ThreadStore>,
profile_id: Arc<str>, profile_id: AgentProfileId,
profile: AgentProfile, profile: AgentProfile,
cx: &mut Context<ToolPicker>, cx: &mut Context<ToolPicker>,
) -> Self { ) -> Self {

View file

@ -1,6 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use assistant_settings::{AgentProfile, AssistantSettings}; use assistant_settings::{AgentProfile, AgentProfileId, AssistantSettings};
use fs::Fs; use fs::Fs;
use gpui::{Action, Entity, FocusHandle, Subscription, WeakEntity, prelude::*}; use gpui::{Action, Entity, FocusHandle, Subscription, WeakEntity, prelude::*};
use indexmap::IndexMap; use indexmap::IndexMap;
@ -15,7 +15,7 @@ use util::ResultExt as _;
use crate::{ManageProfiles, ThreadStore, ToggleProfileSelector}; use crate::{ManageProfiles, ThreadStore, ToggleProfileSelector};
pub struct ProfileSelector { pub struct ProfileSelector {
profiles: IndexMap<Arc<str>, AgentProfile>, profiles: IndexMap<AgentProfileId, AgentProfile>,
fs: Arc<dyn Fs>, fs: Arc<dyn Fs>,
thread_store: WeakEntity<ThreadStore>, thread_store: WeakEntity<ThreadStore>,
focus_handle: FocusHandle, focus_handle: FocusHandle,
@ -133,7 +133,7 @@ impl Render for ProfileSelector {
.active_model() .active_model()
.map_or(false, |model| model.supports_tools()); .map_or(false, |model| model.supports_tools());
let icon = match profile_id.as_ref() { let icon = match profile_id.as_str() {
"write" => IconName::Pencil, "write" => IconName::Pencil,
"ask" => IconName::MessageBubbles, "ask" => IconName::MessageBubbles,
_ => IconName::UserRoundPen, _ => IconName::UserRoundPen,

View file

@ -3,7 +3,7 @@ use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use anyhow::{Result, anyhow}; use anyhow::{Result, anyhow};
use assistant_settings::{AgentProfile, AssistantSettings}; use assistant_settings::{AgentProfile, AgentProfileId, AssistantSettings};
use assistant_tool::{ToolId, ToolSource, ToolWorkingSet}; use assistant_tool::{ToolId, ToolSource, ToolWorkingSet};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use collections::HashMap; use collections::HashMap;
@ -202,7 +202,7 @@ impl ThreadStore {
self.load_profile_by_id(&assistant_settings.default_profile, cx); self.load_profile_by_id(&assistant_settings.default_profile, cx);
} }
pub fn load_profile_by_id(&self, profile_id: &Arc<str>, cx: &Context<Self>) { pub fn load_profile_by_id(&self, profile_id: &AgentProfileId, cx: &Context<Self>) {
let assistant_settings = AssistantSettings::get_global(cx); let assistant_settings = AssistantSettings::get_global(cx);
if let Some(profile) = assistant_settings.profiles.get(profile_id) { if let Some(profile) = assistant_settings.profiles.get(profile_id) {

View file

@ -2,6 +2,29 @@ use std::sync::Arc;
use gpui::SharedString; use gpui::SharedString;
use indexmap::IndexMap; use indexmap::IndexMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AgentProfileId(pub Arc<str>);
impl AgentProfileId {
pub fn as_str(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for AgentProfileId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Default for AgentProfileId {
fn default() -> Self {
Self("write".into())
}
}
/// A profile for the Zed Agent that controls its behavior. /// A profile for the Zed Agent that controls its behavior.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -81,8 +81,8 @@ 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 default_profile: Arc<str>, pub default_profile: AgentProfileId,
pub profiles: IndexMap<Arc<str>, AgentProfile>, pub profiles: IndexMap<AgentProfileId, AgentProfile>,
pub always_allow_tool_actions: bool, pub always_allow_tool_actions: bool,
pub notify_when_agent_waiting: NotifyWhenAgentWaiting, pub notify_when_agent_waiting: NotifyWhenAgentWaiting,
} }
@ -325,7 +325,7 @@ impl AssistantSettingsContent {
} }
} }
pub fn set_profile(&mut self, profile_id: Arc<str>) { pub fn set_profile(&mut self, profile_id: AgentProfileId) {
let AssistantSettingsContent::Versioned(VersionedAssistantSettingsContent::V2(settings)) = let AssistantSettingsContent::Versioned(VersionedAssistantSettingsContent::V2(settings)) =
self self
else { else {
@ -335,7 +335,11 @@ impl AssistantSettingsContent {
settings.default_profile = Some(profile_id); settings.default_profile = Some(profile_id);
} }
pub fn create_profile(&mut self, profile_id: Arc<str>, profile: AgentProfile) -> Result<()> { pub fn create_profile(
&mut self,
profile_id: AgentProfileId,
profile: AgentProfile,
) -> Result<()> {
let AssistantSettingsContent::Versioned(VersionedAssistantSettingsContent::V2(settings)) = let AssistantSettingsContent::Versioned(VersionedAssistantSettingsContent::V2(settings)) =
self self
else { else {
@ -436,9 +440,9 @@ pub struct AssistantSettingsContentV2 {
/// The default profile to use in the Agent. /// The default profile to use in the Agent.
/// ///
/// Default: write /// Default: write
default_profile: Option<Arc<str>>, default_profile: Option<AgentProfileId>,
/// The available agent profiles. /// The available agent profiles.
pub profiles: Option<IndexMap<Arc<str>, AgentProfileContent>>, pub profiles: Option<IndexMap<AgentProfileId, AgentProfileContent>>,
/// Whenever a tool action would normally wait for your confirmation /// Whenever a tool action would normally wait for your confirmation
/// that you allow it, always choose to allow it. /// that you allow it, always choose to allow it.
/// ///