gestura_core_mcp/
prompts.rs

1//! MCP Prompts - Templated messages and workflows
2//! Provides prompt definitions for voice commands and common workflows.
3
4use super::types::{
5    Prompt, PromptArgument, PromptContent, PromptMessage, PromptRole, PromptsGetResult, TextContent,
6};
7use std::collections::HashMap;
8
9/// Prompt registry for managing available prompts
10#[derive(Debug, Default)]
11pub struct PromptRegistry {
12    prompts: HashMap<String, RegisteredPrompt>,
13}
14
15/// A registered prompt with its handler
16#[derive(Debug, Clone)]
17pub struct RegisteredPrompt {
18    pub definition: Prompt,
19    pub template: String,
20}
21
22impl PromptRegistry {
23    /// Create a new prompt registry with default prompts
24    pub fn new() -> Self {
25        let mut registry = Self::default();
26        registry.register_default_prompts();
27        registry
28    }
29
30    /// Register default voice command prompts
31    fn register_default_prompts(&mut self) {
32        // Voice command prompt
33        self.register(RegisteredPrompt {
34            definition: Prompt {
35                name: "voice-command".to_string(),
36                description: Some(
37                    "Process a voice command and generate an appropriate response".to_string(),
38                ),
39                arguments: Some(vec![
40                    PromptArgument {
41                        name: "command".to_string(),
42                        description: Some("The transcribed voice command".to_string()),
43                        required: true,
44                    },
45                    PromptArgument {
46                        name: "context".to_string(),
47                        description: Some("Additional context about the user's environment".to_string()),
48                        required: false,
49                    },
50                ]),
51            },
52            template: "You are a voice assistant. Process this command: {{command}}\n\nContext: {{context}}".to_string(),
53        });
54
55        // Haptic feedback prompt
56        self.register(RegisteredPrompt {
57            definition: Prompt {
58                name: "haptic-feedback".to_string(),
59                description: Some(
60                    "Generate haptic feedback pattern based on notification type".to_string(),
61                ),
62                arguments: Some(vec![
63                    PromptArgument {
64                        name: "notification_type".to_string(),
65                        description: Some(
66                            "Type of notification (alert, message, reminder)".to_string(),
67                        ),
68                        required: true,
69                    },
70                    PromptArgument {
71                        name: "urgency".to_string(),
72                        description: Some("Urgency level (low, medium, high)".to_string()),
73                        required: false,
74                    },
75                ]),
76            },
77            template:
78                "Generate a haptic pattern for: {{notification_type}} with urgency: {{urgency}}"
79                    .to_string(),
80        });
81
82        // Code assistance prompt
83        self.register(RegisteredPrompt {
84            definition: Prompt {
85                name: "code-assist".to_string(),
86                description: Some("Assist with code-related tasks via voice".to_string()),
87                arguments: Some(vec![
88                    PromptArgument {
89                        name: "task".to_string(),
90                        description: Some("The coding task to perform".to_string()),
91                        required: true,
92                    },
93                    PromptArgument {
94                        name: "language".to_string(),
95                        description: Some("Programming language".to_string()),
96                        required: false,
97                    },
98                    PromptArgument {
99                        name: "file_context".to_string(),
100                        description: Some("Current file or code context".to_string()),
101                        required: false,
102                    },
103                ]),
104            },
105            template: "Help with this coding task: {{task}}\nLanguage: {{language}}\nContext: {{file_context}}".to_string(),
106        });
107
108        // System control prompt
109        self.register(RegisteredPrompt {
110            definition: Prompt {
111                name: "system-control".to_string(),
112                description: Some("Control system settings and preferences".to_string()),
113                arguments: Some(vec![PromptArgument {
114                    name: "action".to_string(),
115                    description: Some("The system action to perform".to_string()),
116                    required: true,
117                }]),
118            },
119            template: "Execute system control action: {{action}}".to_string(),
120        });
121    }
122
123    /// Register a prompt
124    pub fn register(&mut self, prompt: RegisteredPrompt) {
125        self.prompts.insert(prompt.definition.name.clone(), prompt);
126    }
127
128    /// List all prompts
129    pub fn list(&self) -> Vec<Prompt> {
130        self.prompts
131            .values()
132            .map(|p| p.definition.clone())
133            .collect()
134    }
135
136    /// Get a prompt by name and render with arguments
137    pub fn get(
138        &self,
139        name: &str,
140        arguments: Option<&HashMap<String, String>>,
141    ) -> Option<PromptsGetResult> {
142        let registered = self.prompts.get(name)?;
143
144        // Render template with arguments
145        let mut rendered = registered.template.clone();
146        if let Some(args) = arguments {
147            for (key, value) in args {
148                rendered = rendered.replace(&format!("{{{{{}}}}}", key), value);
149            }
150        }
151        // Replace any remaining placeholders with empty string
152        rendered = regex::Regex::new(r"\{\{[^}]+\}\}")
153            .ok()?
154            .replace_all(&rendered, "")
155            .to_string();
156
157        Some(PromptsGetResult {
158            description: registered.definition.description.clone(),
159            messages: vec![PromptMessage {
160                role: PromptRole::User,
161                content: PromptContent::Text(TextContent::new(rendered)),
162            }],
163        })
164    }
165
166    /// Check if a prompt exists
167    pub fn contains(&self, name: &str) -> bool {
168        self.prompts.contains_key(name)
169    }
170}