1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Debug, Serialize, Deserialize, Clone)]
5pub struct InstructionPreset {
6 pub name: String,
7 pub description: String,
8 pub instructions: String,
9 pub emoji: String, }
11
12#[derive(Debug, Serialize, Deserialize)]
13pub struct InstructionPresetLibrary {
14 presets: HashMap<String, InstructionPreset>,
15}
16
17impl Default for InstructionPresetLibrary {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl InstructionPresetLibrary {
24 #[allow(clippy::too_many_lines)]
25 pub fn new() -> Self {
26 let mut presets = HashMap::new();
27
28 presets.insert(
29 "default".to_string(),
30 InstructionPreset {
31 name: "Default".to_string(),
32 description: "Standard professional style".to_string(),
33 instructions: "Provide clear, concise, and professional responses. Focus on accuracy and relevance.".to_string(),
34 emoji: "📝".to_string(),
35 },
36 );
37
38 presets.insert(
39 "detailed".to_string(),
40 InstructionPreset {
41 name: "Detailed".to_string(),
42 description: "Provide more context and explanation".to_string(),
43 instructions: "Offer comprehensive explanations, including background information, potential impacts, and related considerations. Aim for thoroughness while maintaining clarity.".to_string(),
44 emoji: "🔍".to_string(),
45 },
46 );
47
48 presets.insert(
49 "concise".to_string(),
50 InstructionPreset {
51 name: "Concise".to_string(),
52 description: "Short and to-the-point responses".to_string(),
53 instructions: "Keep responses brief and focused on the core information. Prioritize essential details and avoid unnecessary elaboration.".to_string(),
54 emoji: "🎯".to_string(),
55 },
56 );
57
58 presets.insert(
59 "technical".to_string(),
60 InstructionPreset {
61 name: "Technical".to_string(),
62 description: "Focus on technical details".to_string(),
63 instructions: "Emphasize technical aspects in your responses. Include specific terminology, methodologies, or performance impacts where relevant. Assume a technically proficient audience.".to_string(),
64 emoji: "⚙️".to_string(),
65 },
66 );
67
68 presets.insert(
69 "storyteller".to_string(),
70 InstructionPreset {
71 name: "Storyteller".to_string(),
72 description: "Frame information as part of an ongoing narrative".to_string(),
73 instructions: "Present information as if it's part of a larger story. Use narrative elements to describe changes, developments, or features. Connect individual elements to create a cohesive narrative arc.".to_string(),
74 emoji: "📚".to_string(),
75 },
76 );
77
78 presets.insert(
79 "emoji-lover".to_string(),
80 InstructionPreset {
81 name: "Emoji Enthusiast".to_string(),
82 description: "Use emojis to enhance communication".to_string(),
83 instructions: "Incorporate relevant emojis throughout your responses to add visual flair and quickly convey the nature of the information. Ensure emojis complement rather than replace clear communication.".to_string(),
84 emoji: "😍".to_string(),
85 },
86 );
87
88 presets.insert(
89 "formal".to_string(),
90 InstructionPreset {
91 name: "Formal".to_string(),
92 description: "Maintain a highly professional and formal tone".to_string(),
93 instructions: "Use formal language and structure in your responses. Avoid colloquialisms and maintain a respectful, business-like tone throughout.".to_string(),
94 emoji: "🎩".to_string(),
95 },
96 );
97
98 presets.insert(
99 "explanatory".to_string(),
100 InstructionPreset {
101 name: "Explanatory".to_string(),
102 description: "Focus on explaining concepts and changes".to_string(),
103 instructions: "Prioritize explaining the 'why' behind information or changes. Provide context, rationale, and potential implications to foster understanding.".to_string(),
104 emoji: "💡".to_string(),
105 },
106 );
107
108 presets.insert(
109 "user-focused".to_string(),
110 InstructionPreset {
111 name: "User-Focused".to_string(),
112 description: "Emphasize user impact and benefits".to_string(),
113 instructions: "Frame information in terms of its impact on users or stakeholders. Highlight benefits, improvements, and how changes affect the user experience.".to_string(),
114 emoji: "👥".to_string(),
115 },
116 );
117
118 presets.insert(
119 "cosmic".to_string(),
120 InstructionPreset {
121 name: "Cosmic Oracle".to_string(),
122 description: "Channel mystical and cosmic energy".to_string(),
123 instructions: "Envision yourself as a cosmic entity, peering into the vast expanse of possibilities. Describe information as if they are celestial events or shifts in the fabric of reality. Use mystical and space-themed language to convey the essence and impact of each element.".to_string(),
124 emoji: "🔮".to_string(),
125 },
126 );
127
128 presets.insert(
129 "academic".to_string(),
130 InstructionPreset {
131 name: "Academic".to_string(),
132 description: "Scholarly and research-oriented style".to_string(),
133 instructions: "Adopt an academic tone, citing relevant sources or methodologies where applicable. Use precise language and maintain a formal, analytical approach to the subject matter.".to_string(),
134 emoji: "🎓".to_string(),
135 },
136 );
137
138 presets.insert(
139 "comparative".to_string(),
140 InstructionPreset {
141 name: "Comparative".to_string(),
142 description: "Highlight differences and similarities".to_string(),
143 instructions: "Focus on comparing and contrasting elements. Identify key differences and similarities, and explain their significance or implications.".to_string(),
144 emoji: "⚖️".to_string(),
145 },
146 );
147
148 presets.insert(
149 "future-oriented".to_string(),
150 InstructionPreset {
151 name: "Future-Oriented".to_string(),
152 description: "Emphasize future implications and possibilities".to_string(),
153 instructions: "Frame information in terms of its future impact. Discuss potential developments, long-term consequences, and how current changes might shape future scenarios.".to_string(),
154 emoji: "🔮".to_string(),
155 },
156 );
157
158 presets.insert(
159 "time-traveler".to_string(),
160 InstructionPreset {
161 name: "Time Traveler".to_string(),
162 description: "Narrate from different points in time".to_string(),
163 instructions: "Imagine you're a time traveler, jumping between past, present, and future. Describe current information as if you're reporting from different time periods. Use appropriate historical or futuristic language and references, and highlight how perspectives change across time.".to_string(),
164 emoji: "⏳".to_string(),
165 },
166 );
167
168 presets.insert(
169 "chef-special".to_string(),
170 InstructionPreset {
171 name: "Chef's Special".to_string(),
172 description: "Present information as a culinary experience".to_string(),
173 instructions: "Treat the information as ingredients in a gourmet meal. Describe changes or updates as if you're crafting a recipe or presenting a dish. Use culinary terms, cooking metaphors, and sensory descriptions to make the content more flavorful and engaging.".to_string(),
174 emoji: "👩🍳".to_string(),
175 },
176 );
177
178 presets.insert(
179 "superhero-saga".to_string(),
180 InstructionPreset {
181 name: "Superhero Saga".to_string(),
182 description: "Frame information in a superhero universe".to_string(),
183 instructions: "Imagine the project or product as a superhero universe. Describe features, changes, or updates as if they're superpowers, epic battles, or heroic adventures. Use dramatic, comic-book style language and frame developments in terms of heroes, villains, and saving the day.".to_string(),
184 emoji: "🦸".to_string(),
185 },
186 );
187
188 presets.insert(
189 "nature-documentary".to_string(),
190 InstructionPreset {
191 name: "Nature Documentary".to_string(),
192 description: "Narrate as if observing a natural phenomenon".to_string(),
193 instructions: "Channel your inner David Attenborough and describe the information as if you're narrating a nature documentary. Treat code, features, or processes as flora and fauna in a complex ecosystem. Use a tone of fascination and wonder, and explain interactions and developments as if observing them in their natural habitat.".to_string(),
194 emoji: "🌿".to_string(),
195 },
196 );
197
198 presets.insert(
199 "chill".to_string(),
200 InstructionPreset {
201 name: "Chill".to_string(),
202 description: "Professional but fun commit messages".to_string(),
203 instructions: "Use a style that's professionally informative but with a touch of clever humor. Keep it light and engaging while still conveying the essential information.".to_string(),
204 emoji: "😎".to_string(),
205 }
206 );
207
208 presets.insert(
209 "hater".to_string(),
210 InstructionPreset {
211 name: "Hater".to_string(),
212 description: "Hyper-critical and brutally honest style".to_string(),
213 instructions: "Adopt a hyper-critical approach. Focus on finding flaws, weaknesses, and potential issues. Provide brutally honest feedback and don't hesitate to point out even minor imperfections.".to_string(),
214 emoji: "💢".to_string(),
215 },
216 );
217
218 presets.insert(
219 "conventional".to_string(),
220 InstructionPreset {
221 name: "Conventional Commits".to_string(),
222 description: "Follow the Conventional Commits specification".to_string(),
223 instructions: "Use the Conventional Commits format: <type>[optional scope]: <description>\n\
224 Valid types are: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert\n\
225 Use the imperative mood in the subject line\n\
226 Limit the subject line to 50 characters if possible, never exceed 72\n\
227 Separate subject from body with a blank line\n\
228 Use the body to explain what and why, wrapping at 72 characters".to_string(),
229 emoji: "📏".to_string(),
230 },
231 );
232
233 Self { presets }
234 }
235
236 pub fn get_preset(&self, key: &str) -> Option<&InstructionPreset> {
237 self.presets.get(key)
238 }
239
240 pub fn list_presets(&self) -> Vec<(&String, &InstructionPreset)> {
241 self.presets.iter().collect()
242 }
243}
244
245pub fn get_instruction_preset_library() -> InstructionPresetLibrary {
246 InstructionPresetLibrary::new()
247}
248
249pub fn list_presets_formatted(library: &InstructionPresetLibrary) -> String {
250 let mut presets: Vec<_> = library.list_presets();
251 presets.sort_by(|a, b| {
252 if a.1.name == "Default" {
253 std::cmp::Ordering::Less
254 } else if b.1.name == "Default" {
255 std::cmp::Ordering::Greater
256 } else {
257 a.1.name.cmp(&b.1.name)
258 }
259 });
260
261 presets
262 .iter()
263 .map(|(key, preset)| {
264 format!(
265 "{} - {} - {} - {}",
266 key, preset.emoji, preset.name, preset.description
267 )
268 })
269 .collect::<Vec<String>>()
270 .join("\n")
271}