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