1mod agent_profile;
2
3use std::sync::Arc;
4
5use agent_client_protocol::ModelId;
6use collections::{HashSet, IndexMap};
7use gpui::{App, Pixels, px};
8use language_model::LanguageModel;
9use project::DisableAiSettings;
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12use settings::{
13 DefaultAgentView, DockPosition, DockSide, LanguageModelParameters, LanguageModelSelection,
14 NotifyWhenAgentWaiting, RegisterSetting, Settings,
15};
16
17pub use crate::agent_profile::*;
18
19pub const SUMMARIZE_THREAD_PROMPT: &str = include_str!("prompts/summarize_thread_prompt.txt");
20pub const SUMMARIZE_THREAD_DETAILED_PROMPT: &str =
21 include_str!("prompts/summarize_thread_detailed_prompt.txt");
22
23#[derive(Clone, Debug, RegisterSetting)]
24pub struct AgentSettings {
25 pub enabled: bool,
26 pub button: bool,
27 pub dock: DockPosition,
28 pub agents_panel_dock: DockSide,
29 pub default_width: Pixels,
30 pub default_height: Pixels,
31 pub default_model: Option<LanguageModelSelection>,
32 pub inline_assistant_model: Option<LanguageModelSelection>,
33 pub inline_assistant_use_streaming_tools: bool,
34 pub commit_message_model: Option<LanguageModelSelection>,
35 pub thread_summary_model: Option<LanguageModelSelection>,
36 pub inline_alternatives: Vec<LanguageModelSelection>,
37 pub favorite_models: Vec<LanguageModelSelection>,
38 pub default_profile: AgentProfileId,
39 pub default_view: DefaultAgentView,
40 pub profiles: IndexMap<AgentProfileId, AgentProfileSettings>,
41 pub always_allow_tool_actions: bool,
42 pub notify_when_agent_waiting: NotifyWhenAgentWaiting,
43 pub play_sound_when_agent_done: bool,
44 pub single_file_review: bool,
45 pub model_parameters: Vec<LanguageModelParameters>,
46 pub preferred_completion_mode: CompletionMode,
47 pub enable_feedback: bool,
48 pub expand_edit_card: bool,
49 pub expand_terminal_card: bool,
50 pub use_modifier_to_send: bool,
51 pub message_editor_min_lines: usize,
52}
53
54impl AgentSettings {
55 pub fn enabled(&self, cx: &App) -> bool {
56 self.enabled && !DisableAiSettings::get_global(cx).disable_ai
57 }
58
59 pub fn temperature_for_model(model: &Arc<dyn LanguageModel>, cx: &App) -> Option<f32> {
60 let settings = Self::get_global(cx);
61 for setting in settings.model_parameters.iter().rev() {
62 if let Some(provider) = &setting.provider
63 && provider.0 != model.provider_id().0
64 {
65 continue;
66 }
67 if let Some(setting_model) = &setting.model
68 && *setting_model != model.id().0
69 {
70 continue;
71 }
72 return setting.temperature;
73 }
74 return None;
75 }
76
77 pub fn set_inline_assistant_model(&mut self, provider: String, model: String) {
78 self.inline_assistant_model = Some(LanguageModelSelection {
79 provider: provider.into(),
80 model,
81 });
82 }
83
84 pub fn set_commit_message_model(&mut self, provider: String, model: String) {
85 self.commit_message_model = Some(LanguageModelSelection {
86 provider: provider.into(),
87 model,
88 });
89 }
90
91 pub fn set_thread_summary_model(&mut self, provider: String, model: String) {
92 self.thread_summary_model = Some(LanguageModelSelection {
93 provider: provider.into(),
94 model,
95 });
96 }
97
98 pub fn set_message_editor_max_lines(&self) -> usize {
99 self.message_editor_min_lines * 2
100 }
101
102 pub fn favorite_model_ids(&self) -> HashSet<ModelId> {
103 self.favorite_models
104 .iter()
105 .map(|sel| ModelId::new(format!("{}/{}", sel.provider.0, sel.model)))
106 .collect()
107 }
108}
109
110#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
111#[serde(rename_all = "snake_case")]
112pub enum CompletionMode {
113 #[default]
114 Normal,
115 #[serde(alias = "max")]
116 Burn,
117}
118
119impl From<CompletionMode> for cloud_llm_client::CompletionMode {
120 fn from(value: CompletionMode) -> Self {
121 match value {
122 CompletionMode::Normal => cloud_llm_client::CompletionMode::Normal,
123 CompletionMode::Burn => cloud_llm_client::CompletionMode::Max,
124 }
125 }
126}
127
128impl From<settings::CompletionMode> for CompletionMode {
129 fn from(value: settings::CompletionMode) -> Self {
130 match value {
131 settings::CompletionMode::Normal => CompletionMode::Normal,
132 settings::CompletionMode::Burn => CompletionMode::Burn,
133 }
134 }
135}
136
137#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize, JsonSchema)]
138pub struct AgentProfileId(pub Arc<str>);
139
140impl AgentProfileId {
141 pub fn as_str(&self) -> &str {
142 &self.0
143 }
144}
145
146impl std::fmt::Display for AgentProfileId {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 write!(f, "{}", self.0)
149 }
150}
151
152impl Default for AgentProfileId {
153 fn default() -> Self {
154 Self("write".into())
155 }
156}
157
158impl Settings for AgentSettings {
159 fn from_settings(content: &settings::SettingsContent) -> Self {
160 let agent = content.agent.clone().unwrap();
161 Self {
162 enabled: agent.enabled.unwrap(),
163 button: agent.button.unwrap(),
164 dock: agent.dock.unwrap(),
165 agents_panel_dock: agent.agents_panel_dock.unwrap(),
166 default_width: px(agent.default_width.unwrap()),
167 default_height: px(agent.default_height.unwrap()),
168 default_model: Some(agent.default_model.unwrap()),
169 inline_assistant_model: agent.inline_assistant_model,
170 inline_assistant_use_streaming_tools: agent
171 .inline_assistant_use_streaming_tools
172 .unwrap_or(true),
173 commit_message_model: agent.commit_message_model,
174 thread_summary_model: agent.thread_summary_model,
175 inline_alternatives: agent.inline_alternatives.unwrap_or_default(),
176 favorite_models: agent.favorite_models,
177 default_profile: AgentProfileId(agent.default_profile.unwrap()),
178 default_view: agent.default_view.unwrap(),
179 profiles: agent
180 .profiles
181 .unwrap()
182 .into_iter()
183 .map(|(key, val)| (AgentProfileId(key), val.into()))
184 .collect(),
185 always_allow_tool_actions: agent.always_allow_tool_actions.unwrap(),
186 notify_when_agent_waiting: agent.notify_when_agent_waiting.unwrap(),
187 play_sound_when_agent_done: agent.play_sound_when_agent_done.unwrap(),
188 single_file_review: agent.single_file_review.unwrap(),
189 model_parameters: agent.model_parameters,
190 preferred_completion_mode: agent.preferred_completion_mode.unwrap().into(),
191 enable_feedback: agent.enable_feedback.unwrap(),
192 expand_edit_card: agent.expand_edit_card.unwrap(),
193 expand_terminal_card: agent.expand_terminal_card.unwrap(),
194 use_modifier_to_send: agent.use_modifier_to_send.unwrap(),
195 message_editor_min_lines: agent.message_editor_min_lines.unwrap(),
196 }
197 }
198}