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