1use crate::CodePrismMcpServer;
8use anyhow::Result;
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct PromptCapabilities {
15 #[serde(rename = "listChanged")]
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub list_changed: Option<bool>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct Prompt {
24 pub name: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub title: Option<String>,
29 pub description: String,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub arguments: Option<Vec<PromptArgument>>,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct PromptArgument {
39 pub name: String,
41 pub description: String,
43 pub required: bool,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct PromptMessage {
50 pub role: String,
52 pub content: PromptContent,
54}
55
56#[derive(Debug, Clone, Serialize, Deserialize)]
58#[serde(tag = "type")]
59pub enum PromptContent {
60 #[serde(rename = "text")]
62 Text {
63 text: String,
65 },
66 #[serde(rename = "image")]
68 Image {
69 data: String,
71 #[serde(rename = "mimeType")]
73 mime_type: String,
74 },
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct GetPromptParams {
80 pub name: String,
82 #[serde(skip_serializing_if = "Option::is_none")]
84 pub arguments: Option<serde_json::Map<String, Value>>,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct GetPromptResult {
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub description: Option<String>,
93 pub messages: Vec<PromptMessage>,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct ListPromptsParams {
100 #[serde(skip_serializing_if = "Option::is_none")]
102 pub cursor: Option<String>,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct ListPromptsResult {
108 pub prompts: Vec<Prompt>,
110 #[serde(rename = "nextCursor")]
112 #[serde(skip_serializing_if = "Option::is_none")]
113 pub next_cursor: Option<String>,
114}
115
116pub struct PromptManager {
118 server: std::sync::Arc<tokio::sync::RwLock<CodePrismMcpServer>>,
119}
120
121impl PromptManager {
122 pub fn new(server: std::sync::Arc<tokio::sync::RwLock<CodePrismMcpServer>>) -> Self {
124 Self { server }
125 }
126
127 pub async fn list_prompts(&self, _params: ListPromptsParams) -> Result<ListPromptsResult> {
129 let prompts = vec![
130 Prompt {
131 name: "repository_overview".to_string(),
132 title: Some("Repository Overview".to_string()),
133 description: "Generate a comprehensive overview of the repository structure and contents".to_string(),
134 arguments: Some(vec![
135 PromptArgument {
136 name: "focus_area".to_string(),
137 description: "Optional area to focus on (architecture, dependencies, entry_points, etc.)".to_string(),
138 required: false,
139 },
140 ]),
141 },
142
143 Prompt {
144 name: "code_analysis".to_string(),
145 title: Some("Code Analysis".to_string()),
146 description: "Analyze code quality, patterns, and potential improvements".to_string(),
147 arguments: Some(vec![
148 PromptArgument {
149 name: "file_pattern".to_string(),
150 description: "Optional file pattern to focus analysis on".to_string(),
151 required: false,
152 },
153 PromptArgument {
154 name: "analysis_type".to_string(),
155 description: "Type of analysis (quality, security, performance, architecture)".to_string(),
156 required: false,
157 },
158 ]),
159 },
160
161 Prompt {
162 name: "debug_assistance".to_string(),
163 title: Some("Debug Assistance".to_string()),
164 description: "Help debug issues in the codebase with contextual information".to_string(),
165 arguments: Some(vec![
166 PromptArgument {
167 name: "issue_description".to_string(),
168 description: "Description of the issue or error".to_string(),
169 required: true,
170 },
171 PromptArgument {
172 name: "affected_files".to_string(),
173 description: "Files related to the issue".to_string(),
174 required: false,
175 },
176 ]),
177 },
178
179 Prompt {
180 name: "debug_issue".to_string(),
181 title: Some("Debug Issue".to_string()),
182 description: "Analyze potential bug sources and dependencies for debugging".to_string(),
183 arguments: Some(vec![
184 PromptArgument {
185 name: "error_location".to_string(),
186 description: "File and line where error occurs".to_string(),
187 required: true,
188 },
189 PromptArgument {
190 name: "error_message".to_string(),
191 description: "Error message or description".to_string(),
192 required: false,
193 },
194 ]),
195 },
196
197 Prompt {
198 name: "refactoring_guidance".to_string(),
199 title: Some("Refactoring Guidance".to_string()),
200 description: "Provide guidance for refactoring code with repository context".to_string(),
201 arguments: Some(vec![
202 PromptArgument {
203 name: "target_area".to_string(),
204 description: "Area of code to refactor".to_string(),
205 required: true,
206 },
207 PromptArgument {
208 name: "refactoring_goal".to_string(),
209 description: "Goal of the refactoring (performance, maintainability, etc.)".to_string(),
210 required: false,
211 },
212 ]),
213 },
214
215 Prompt {
216 name: "architectural_analysis".to_string(),
217 title: Some("Architectural Analysis".to_string()),
218 description: "Analyze the overall architecture, patterns, and structural design of the codebase".to_string(),
219 arguments: Some(vec![
220 PromptArgument {
221 name: "analysis_focus".to_string(),
222 description: "Focus area for analysis (layers, patterns, dependencies, coupling)".to_string(),
223 required: false,
224 },
225 PromptArgument {
226 name: "architectural_concerns".to_string(),
227 description: "Specific architectural concerns or questions".to_string(),
228 required: false,
229 },
230 ]),
231 },
232
233 Prompt {
234 name: "pattern_assessment".to_string(),
235 title: Some("Design Pattern Assessment".to_string()),
236 description: "Assess design patterns usage and suggest architectural improvements".to_string(),
237 arguments: Some(vec![
238 PromptArgument {
239 name: "pattern_types".to_string(),
240 description: "Types of patterns to focus on (design_patterns, anti_patterns, architectural_patterns)".to_string(),
241 required: false,
242 },
243 PromptArgument {
244 name: "improvement_scope".to_string(),
245 description: "Scope of improvements to suggest (immediate, long-term, strategic)".to_string(),
246 required: false,
247 },
248 ]),
249 },
250
251 Prompt {
252 name: "dependency_analysis".to_string(),
253 title: Some("Dependency Analysis".to_string()),
254 description: "Analyze dependencies, coupling, and suggest decoupling strategies".to_string(),
255 arguments: Some(vec![
256 PromptArgument {
257 name: "analysis_target".to_string(),
258 description: "Target for analysis (file, class, module, or repository-wide)".to_string(),
259 required: false,
260 },
261 PromptArgument {
262 name: "dependency_concerns".to_string(),
263 description: "Specific dependency concerns (cycles, coupling, cohesion)".to_string(),
264 required: false,
265 },
266 ]),
267 },
268
269 Prompt {
271 name: "new_developer_onboarding".to_string(),
272 title: Some("New Developer Onboarding".to_string()),
273 description: "Create a comprehensive onboarding guide for new developers joining the project".to_string(),
274 arguments: Some(vec![
275 PromptArgument {
276 name: "developer_experience".to_string(),
277 description: "Developer's experience level (junior, mid, senior)".to_string(),
278 required: false,
279 },
280 PromptArgument {
281 name: "focus_areas".to_string(),
282 description: "Areas the developer should focus on first (frontend, backend, infrastructure, etc.)".to_string(),
283 required: false,
284 },
285 PromptArgument {
286 name: "timeline".to_string(),
287 description: "Onboarding timeline (1-week, 2-week, 1-month)".to_string(),
288 required: false,
289 },
290 ]),
291 },
292
293 Prompt {
294 name: "feature_exploration".to_string(),
295 title: Some("Feature Exploration".to_string()),
296 description: "Deep dive into understanding a specific feature or module in the codebase".to_string(),
297 arguments: Some(vec![
298 PromptArgument {
299 name: "feature_name".to_string(),
300 description: "Name or description of the feature to explore".to_string(),
301 required: true,
302 },
303 PromptArgument {
304 name: "exploration_depth".to_string(),
305 description: "Depth of exploration (overview, detailed, implementation)".to_string(),
306 required: false,
307 },
308 PromptArgument {
309 name: "include_tests".to_string(),
310 description: "Whether to include test coverage analysis".to_string(),
311 required: false,
312 },
313 ]),
314 },
315
316 Prompt {
317 name: "learning_path_generator".to_string(),
318 title: Some("Learning Path Generator".to_string()),
319 description: "Generate a guided learning path through the codebase for specific goals".to_string(),
320 arguments: Some(vec![
321 PromptArgument {
322 name: "learning_goal".to_string(),
323 description: "What the user wants to learn or achieve".to_string(),
324 required: true,
325 },
326 PromptArgument {
327 name: "current_knowledge".to_string(),
328 description: "User's current knowledge level with the codebase".to_string(),
329 required: false,
330 },
331 PromptArgument {
332 name: "time_constraint".to_string(),
333 description: "Available time for learning (1-day, 1-week, 1-month)".to_string(),
334 required: false,
335 },
336 ]),
337 },
338
339 Prompt {
340 name: "technology_stack_analysis".to_string(),
341 title: Some("Technology Stack Analysis".to_string()),
342 description: "Analyze the technology stack, frameworks, and architectural decisions".to_string(),
343 arguments: Some(vec![
344 PromptArgument {
345 name: "analysis_focus".to_string(),
346 description: "Focus area (languages, frameworks, tools, infrastructure)".to_string(),
347 required: false,
348 },
349 PromptArgument {
350 name: "include_alternatives".to_string(),
351 description: "Whether to suggest alternative technologies".to_string(),
352 required: false,
353 },
354 ]),
355 },
356
357 Prompt {
358 name: "codebase_health_check".to_string(),
359 title: Some("Codebase Health Check".to_string()),
360 description: "Comprehensive health assessment of the codebase including quality, maintainability, and technical debt".to_string(),
361 arguments: Some(vec![
362 PromptArgument {
363 name: "health_aspects".to_string(),
364 description: "Aspects to focus on (code_quality, test_coverage, security, performance, maintainability)".to_string(),
365 required: false,
366 },
367 PromptArgument {
368 name: "severity_threshold".to_string(),
369 description: "Minimum severity level for issues to report (low, medium, high, critical)".to_string(),
370 required: false,
371 },
372 ]),
373 },
374
375 Prompt {
376 name: "documentation_generator".to_string(),
377 title: Some("Documentation Generator".to_string()),
378 description: "Generate comprehensive documentation for the codebase or specific components".to_string(),
379 arguments: Some(vec![
380 PromptArgument {
381 name: "documentation_type".to_string(),
382 description: "Type of documentation (API, architecture, developer_guide, user_manual)".to_string(),
383 required: true,
384 },
385 PromptArgument {
386 name: "target_audience".to_string(),
387 description: "Target audience (developers, users, architects, managers)".to_string(),
388 required: false,
389 },
390 PromptArgument {
391 name: "scope".to_string(),
392 description: "Scope of documentation (full_repository, specific_module, specific_feature)".to_string(),
393 required: false,
394 },
395 ]),
396 },
397
398 Prompt {
399 name: "testing_strategy_analysis".to_string(),
400 title: Some("Testing Strategy Analysis".to_string()),
401 description: "Analyze current testing approach and suggest improvements for test coverage and quality".to_string(),
402 arguments: Some(vec![
403 PromptArgument {
404 name: "test_types".to_string(),
405 description: "Types of tests to analyze (unit, integration, e2e, performance)".to_string(),
406 required: false,
407 },
408 PromptArgument {
409 name: "coverage_threshold".to_string(),
410 description: "Minimum coverage threshold to aim for (percentage)".to_string(),
411 required: false,
412 },
413 ]),
414 },
415
416 Prompt {
417 name: "migration_planning".to_string(),
418 title: Some("Migration Planning".to_string()),
419 description: "Plan migration strategies for legacy code, frameworks, or architectural changes".to_string(),
420 arguments: Some(vec![
421 PromptArgument {
422 name: "migration_type".to_string(),
423 description: "Type of migration (framework_upgrade, language_migration, architecture_change)".to_string(),
424 required: true,
425 },
426 PromptArgument {
427 name: "target_technology".to_string(),
428 description: "Target technology or framework to migrate to".to_string(),
429 required: false,
430 },
431 PromptArgument {
432 name: "risk_tolerance".to_string(),
433 description: "Risk tolerance level (low, medium, high)".to_string(),
434 required: false,
435 },
436 ]),
437 },
438 ];
439
440 Ok(ListPromptsResult {
441 prompts,
442 next_cursor: None,
443 })
444 }
445
446 pub async fn get_prompt(&self, params: GetPromptParams) -> Result<GetPromptResult> {
448 let server = self.server.read().await;
449
450 match params.name.as_str() {
451 "repository_overview" => {
452 self.repository_overview_prompt(&server, params.arguments)
453 .await
454 }
455 "code_analysis" => self.code_analysis_prompt(&server, params.arguments).await,
456 "debug_assistance" => {
457 self.debug_assistance_prompt(&server, params.arguments)
458 .await
459 }
460 "debug_issue" => self.debug_issue_prompt(&server, params.arguments).await,
461 "refactoring_guidance" => {
462 self.refactoring_guidance_prompt(&server, params.arguments)
463 .await
464 }
465 "architectural_analysis" => {
466 self.architectural_analysis_prompt(&server, params.arguments)
467 .await
468 }
469 "pattern_assessment" => {
470 self.pattern_assessment_prompt(&server, params.arguments)
471 .await
472 }
473 "dependency_analysis" => {
474 self.dependency_analysis_prompt(&server, params.arguments)
475 .await
476 }
477 "new_developer_onboarding" => {
478 self.new_developer_onboarding_prompt(&server, params.arguments)
479 .await
480 }
481 "feature_exploration" => {
482 self.feature_exploration_prompt(&server, params.arguments)
483 .await
484 }
485 "learning_path_generator" => {
486 self.learning_path_generator_prompt(&server, params.arguments)
487 .await
488 }
489 "technology_stack_analysis" => {
490 self.technology_stack_analysis_prompt(&server, params.arguments)
491 .await
492 }
493 "codebase_health_check" => {
494 self.codebase_health_check_prompt(&server, params.arguments)
495 .await
496 }
497 "documentation_generator" => {
498 self.documentation_generator_prompt(&server, params.arguments)
499 .await
500 }
501 "testing_strategy_analysis" => {
502 self.testing_strategy_analysis_prompt(&server, params.arguments)
503 .await
504 }
505 "migration_planning" => {
506 self.migration_planning_prompt(&server, params.arguments)
507 .await
508 }
509 _ => Err(anyhow::anyhow!("Unknown prompt: {}", params.name)),
510 }
511 }
512
513 async fn repository_overview_prompt(
515 &self,
516 server: &CodePrismMcpServer,
517 arguments: Option<serde_json::Map<String, Value>>,
518 ) -> Result<GetPromptResult> {
519 let focus_area = arguments
520 .as_ref()
521 .and_then(|args| args.get("focus_area"))
522 .and_then(|v| v.as_str())
523 .unwrap_or("general");
524
525 let repo_context = if let Some(repo_path) = server.repository_path() {
526 let file_count = server
527 .scanner()
528 .discover_files(repo_path)
529 .map(|files| files.len())
530 .unwrap_or(0);
531
532 format!(
533 "Repository: {}\nTotal files: {}\nFocus area: {}",
534 repo_path.display(),
535 file_count,
536 focus_area
537 )
538 } else {
539 "No repository currently loaded".to_string()
540 };
541
542 let prompt_text = format!(
543 r#"Please provide a comprehensive overview of this repository with the following context:
544
545{}
546
547Please analyze and provide:
5481. Repository structure and organization
5492. Main technologies and frameworks used
5503. Key entry points and important files
5514. Dependencies and external libraries
5525. Code patterns and architectural decisions
5536. Areas for potential improvement
554
555Focus particularly on: {}
556
557Use the repository resources and tools available to gather detailed information about the codebase."#,
558 repo_context, focus_area
559 );
560
561 Ok(GetPromptResult {
562 description: Some("Repository overview and analysis prompt".to_string()),
563 messages: vec![PromptMessage {
564 role: "user".to_string(),
565 content: PromptContent::Text { text: prompt_text },
566 }],
567 })
568 }
569
570 async fn code_analysis_prompt(
572 &self,
573 server: &CodePrismMcpServer,
574 arguments: Option<serde_json::Map<String, Value>>,
575 ) -> Result<GetPromptResult> {
576 let file_pattern = arguments
577 .as_ref()
578 .and_then(|args| args.get("file_pattern"))
579 .and_then(|v| v.as_str())
580 .unwrap_or("*");
581
582 let analysis_type = arguments
583 .as_ref()
584 .and_then(|args| args.get("analysis_type"))
585 .and_then(|v| v.as_str())
586 .unwrap_or("quality");
587
588 let repo_context = if let Some(repo_path) = server.repository_path() {
589 format!("Repository: {}", repo_path.display())
590 } else {
591 "No repository currently loaded".to_string()
592 };
593
594 let prompt_text = format!(
595 r#"Please perform a {} analysis of the codebase with the following context:
596
597{}
598
599File pattern: {}
600Analysis focus: {}
601
602Please analyze and provide:
6031. Code quality assessment
6042. Potential issues and vulnerabilities
6053. Best practices compliance
6064. Performance considerations
6075. Maintainability factors
6086. Specific recommendations for improvement
609
610Use the available tools to gather detailed information about the code structure and patterns."#,
611 analysis_type, repo_context, file_pattern, analysis_type
612 );
613
614 Ok(GetPromptResult {
615 description: Some("Code analysis and quality assessment prompt".to_string()),
616 messages: vec![PromptMessage {
617 role: "user".to_string(),
618 content: PromptContent::Text { text: prompt_text },
619 }],
620 })
621 }
622
623 async fn debug_assistance_prompt(
625 &self,
626 _server: &CodePrismMcpServer,
627 arguments: Option<serde_json::Map<String, Value>>,
628 ) -> Result<GetPromptResult> {
629 let issue_description = arguments
630 .as_ref()
631 .and_then(|args| args.get("issue_description"))
632 .and_then(|v| v.as_str())
633 .ok_or_else(|| anyhow::anyhow!("issue_description argument is required"))?;
634
635 let affected_files = arguments
636 .as_ref()
637 .and_then(|args| args.get("affected_files"))
638 .and_then(|v| v.as_str())
639 .unwrap_or("unknown");
640
641 let prompt_text = format!(
642 r#"I need help debugging the following issue:
643
644Issue Description: {}
645Affected Files: {}
646
647Please help me:
6481. Understand the root cause of this issue
6492. Identify related code that might be contributing to the problem
6503. Suggest debugging steps and approaches
6514. Provide potential solutions or workarounds
6525. Recommend best practices to prevent similar issues
653
654Use the repository tools to examine the relevant code and dependencies."#,
655 issue_description, affected_files
656 );
657
658 Ok(GetPromptResult {
659 description: Some("Debug assistance with repository context".to_string()),
660 messages: vec![PromptMessage {
661 role: "user".to_string(),
662 content: PromptContent::Text { text: prompt_text },
663 }],
664 })
665 }
666
667 async fn debug_issue_prompt(
669 &self,
670 _server: &CodePrismMcpServer,
671 arguments: Option<serde_json::Map<String, Value>>,
672 ) -> Result<GetPromptResult> {
673 let error_location = arguments
674 .as_ref()
675 .and_then(|args| args.get("error_location"))
676 .and_then(|v| v.as_str())
677 .ok_or_else(|| anyhow::anyhow!("error_location argument is required"))?;
678
679 let error_message = arguments
680 .as_ref()
681 .and_then(|args| args.get("error_message"))
682 .and_then(|v| v.as_str())
683 .unwrap_or("No error message provided");
684
685 let prompt_text = format!(
686 r#"Please analyze the following error:
687
688Error Location: {}
689Error Message: {}
690
691Please provide:
6921. Analysis of the error's source and potential impact
6932. Suggestions for debugging and resolving the issue
6943. Recommendations for preventing similar errors in the future
695
696Use the repository tools to understand the code and dependencies related to this error."#,
697 error_location, error_message
698 );
699
700 Ok(GetPromptResult {
701 description: Some("Debug issue analysis prompt".to_string()),
702 messages: vec![PromptMessage {
703 role: "user".to_string(),
704 content: PromptContent::Text { text: prompt_text },
705 }],
706 })
707 }
708
709 async fn refactoring_guidance_prompt(
711 &self,
712 _server: &CodePrismMcpServer,
713 arguments: Option<serde_json::Map<String, Value>>,
714 ) -> Result<GetPromptResult> {
715 let target_area = arguments
716 .as_ref()
717 .and_then(|args| args.get("target_area"))
718 .and_then(|v| v.as_str())
719 .ok_or_else(|| anyhow::anyhow!("target_area argument is required"))?;
720
721 let refactoring_goal = arguments
722 .as_ref()
723 .and_then(|args| args.get("refactoring_goal"))
724 .and_then(|v| v.as_str())
725 .unwrap_or("improve maintainability");
726
727 let prompt_text = format!(
728 r#"I need guidance for refactoring the following area of the codebase:
729
730Target Area: {}
731Refactoring Goal: {}
732
733Please provide:
7341. Analysis of the current code structure and patterns
7352. Identification of code smells or areas for improvement
7363. Recommended refactoring approach and strategy
7374. Step-by-step refactoring plan
7385. Potential risks and mitigation strategies
7396. Testing considerations during refactoring
740
741Use the repository tools to understand the current implementation and its dependencies."#,
742 target_area, refactoring_goal
743 );
744
745 Ok(GetPromptResult {
746 description: Some("Refactoring guidance with repository analysis".to_string()),
747 messages: vec![PromptMessage {
748 role: "user".to_string(),
749 content: PromptContent::Text { text: prompt_text },
750 }],
751 })
752 }
753
754 async fn architectural_analysis_prompt(
756 &self,
757 _server: &CodePrismMcpServer,
758 arguments: Option<serde_json::Map<String, Value>>,
759 ) -> Result<GetPromptResult> {
760 let analysis_focus = arguments
761 .as_ref()
762 .and_then(|args| args.get("analysis_focus"))
763 .and_then(|v| v.as_str())
764 .unwrap_or("general");
765
766 let prompt_text = format!(
767 r#"Please analyze the overall architecture, patterns, and structural design of the codebase with the following focus:
768
769{}
770
771Please provide:
7721. Analysis of the current architecture
7732. Identification of architectural concerns or questions
7743. Suggestions for architectural improvements
7754. Step-by-step plan for implementing improvements
7765. Potential risks and mitigation strategies
7776. Testing considerations during architectural changes
778
779Use the repository tools to understand the current implementation and its dependencies."#,
780 analysis_focus
781 );
782
783 Ok(GetPromptResult {
784 description: Some("Architectural analysis prompt".to_string()),
785 messages: vec![PromptMessage {
786 role: "user".to_string(),
787 content: PromptContent::Text { text: prompt_text },
788 }],
789 })
790 }
791
792 async fn pattern_assessment_prompt(
794 &self,
795 _server: &CodePrismMcpServer,
796 arguments: Option<serde_json::Map<String, Value>>,
797 ) -> Result<GetPromptResult> {
798 let pattern_types = arguments
799 .as_ref()
800 .and_then(|args| args.get("pattern_types"))
801 .and_then(|v| v.as_str())
802 .unwrap_or("general");
803
804 let _improvement_scope = arguments
805 .as_ref()
806 .and_then(|args| args.get("improvement_scope"))
807 .and_then(|v| v.as_str())
808 .unwrap_or("general");
809
810 let prompt_text = format!(
811 r#"Please assess the usage of design patterns in the codebase with the following focus:
812
813{}
814
815Please provide:
8161. Analysis of the current pattern usage
8172. Identification of patterns that could be improved
8183. Suggestions for architectural improvements based on pattern usage
8194. Step-by-step plan for implementing improvements
8205. Potential risks and mitigation strategies
8216. Testing considerations during architectural changes
822
823Use the repository tools to understand the current implementation and its dependencies."#,
824 pattern_types
825 );
826
827 Ok(GetPromptResult {
828 description: Some("Design pattern assessment prompt".to_string()),
829 messages: vec![PromptMessage {
830 role: "user".to_string(),
831 content: PromptContent::Text { text: prompt_text },
832 }],
833 })
834 }
835
836 async fn dependency_analysis_prompt(
838 &self,
839 _server: &CodePrismMcpServer,
840 arguments: Option<serde_json::Map<String, Value>>,
841 ) -> Result<GetPromptResult> {
842 let _analysis_target = arguments
843 .as_ref()
844 .and_then(|args| args.get("analysis_target"))
845 .and_then(|v| v.as_str())
846 .unwrap_or("general");
847
848 let dependency_concerns = arguments
849 .as_ref()
850 .and_then(|args| args.get("dependency_concerns"))
851 .and_then(|v| v.as_str())
852 .unwrap_or("general");
853
854 let prompt_text = format!(
855 r#"Please analyze dependencies, coupling, and suggest decoupling strategies with the following focus:
856
857{}
858
859Please provide:
8601. Analysis of the current dependency structure
8612. Identification of dependency concerns
8623. Suggestions for decoupling strategies
8634. Step-by-step plan for implementing improvements
8645. Potential risks and mitigation strategies
8656. Testing considerations during architectural changes
866
867Use the repository tools to understand the current implementation and its dependencies."#,
868 dependency_concerns
869 );
870
871 Ok(GetPromptResult {
872 description: Some("Dependency analysis prompt".to_string()),
873 messages: vec![PromptMessage {
874 role: "user".to_string(),
875 content: PromptContent::Text { text: prompt_text },
876 }],
877 })
878 }
879
880 async fn new_developer_onboarding_prompt(
882 &self,
883 server: &CodePrismMcpServer,
884 arguments: Option<serde_json::Map<String, Value>>,
885 ) -> Result<GetPromptResult> {
886 let developer_experience = arguments
887 .as_ref()
888 .and_then(|args| args.get("developer_experience"))
889 .and_then(|v| v.as_str())
890 .unwrap_or("mid");
891
892 let focus_areas = arguments
893 .as_ref()
894 .and_then(|args| args.get("focus_areas"))
895 .and_then(|v| v.as_str())
896 .unwrap_or("general");
897
898 let timeline = arguments
899 .as_ref()
900 .and_then(|args| args.get("timeline"))
901 .and_then(|v| v.as_str())
902 .unwrap_or("2-week");
903
904 let repo_context = if let Some(repo_path) = server.repository_path() {
905 format!("Repository: {}", repo_path.display())
906 } else {
907 "No repository currently loaded".to_string()
908 };
909
910 let prompt_text = format!(
911 r#"Please create a comprehensive onboarding guide for a new {} developer joining this project:
912
913{}
914
915Developer experience level: {}
916Focus areas: {}
917Onboarding timeline: {}
918
919Please provide:
9201. **Repository Overview**: Structure, key directories, and important files
9212. **Technology Stack**: Languages, frameworks, tools, and dependencies
9223. **Development Environment Setup**: Step-by-step setup instructions
9234. **Architecture Understanding**: High-level architecture and design patterns
9245. **Key Features Walkthrough**: Main features and how they work
9256. **Development Workflow**: Coding standards, testing, and deployment processes
9267. **First Tasks**: Suggested starter tasks to get familiar with the codebase
9278. **Learning Resources**: Documentation, wiki, and helpful references
9289. **Team Contacts**: Who to contact for different areas/questions
92910. **Success Metrics**: How to measure onboarding progress
930
931Use repository analysis tools to gather detailed information about:
932- File structure and organization
933- Dependencies and external libraries
934- Code patterns and conventions
935- Test coverage and quality
936- Documentation availability
937
938Tailor the guide to the developer's experience level and focus areas."#,
939 developer_experience, repo_context, developer_experience, focus_areas, timeline
940 );
941
942 Ok(GetPromptResult {
943 description: Some("Comprehensive new developer onboarding guide".to_string()),
944 messages: vec![PromptMessage {
945 role: "user".to_string(),
946 content: PromptContent::Text { text: prompt_text },
947 }],
948 })
949 }
950
951 async fn feature_exploration_prompt(
953 &self,
954 server: &CodePrismMcpServer,
955 arguments: Option<serde_json::Map<String, Value>>,
956 ) -> Result<GetPromptResult> {
957 let feature_name = arguments
958 .as_ref()
959 .and_then(|args| args.get("feature_name"))
960 .and_then(|v| v.as_str())
961 .ok_or_else(|| anyhow::anyhow!("feature_name argument is required"))?;
962
963 let exploration_depth = arguments
964 .as_ref()
965 .and_then(|args| args.get("exploration_depth"))
966 .and_then(|v| v.as_str())
967 .unwrap_or("detailed");
968
969 let include_tests = arguments
970 .as_ref()
971 .and_then(|args| args.get("include_tests"))
972 .and_then(|v| v.as_str())
973 .unwrap_or("true");
974
975 let repo_context = if let Some(repo_path) = server.repository_path() {
976 format!("Repository: {}", repo_path.display())
977 } else {
978 "No repository currently loaded".to_string()
979 };
980
981 let prompt_text = format!(
982 r#"Please provide a comprehensive exploration of the '{}' feature in this codebase:
983
984{}
985
986Exploration depth: {}
987Include test analysis: {}
988
989Please analyze and provide:
990
9911. **Feature Overview**:
992 - Purpose and functionality of the feature
993 - Business value and user impact
994 - High-level architecture
995
9962. **Code Structure**:
997 - Main files and directories related to the feature
998 - Key classes, functions, and modules
999 - Entry points and public APIs
1000
10013. **Implementation Details**:
1002 - Core algorithms and logic
1003 - Data models and structures
1004 - External dependencies and integrations
1005
10064. **Dependencies and Relationships**:
1007 - Dependencies on other features/modules
1008 - Features that depend on this one
1009 - External library dependencies
1010
10115. **Data Flow**:
1012 - How data flows through the feature
1013 - Input/output interfaces
1014 - State management
1015
10166. **Configuration and Settings**:
1017 - Configuration options
1018 - Environment variables
1019 - Feature flags or toggles
1020
1021{}
1022
10237. **Documentation and Comments**:
1024 - Existing documentation
1025 - Code comments and explanations
1026 - Missing documentation areas
1027
10288. **Potential Issues and Improvements**:
1029 - Code quality concerns
1030 - Performance considerations
1031 - Security implications
1032 - Refactoring opportunities
1033
1034Use repository analysis tools to:
1035- Search for relevant files and symbols
1036- Analyze dependencies and references
1037- Examine code patterns and complexity
1038- Trace execution paths
1039
1040Provide specific file paths, function names, and code examples where relevant."#,
1041 feature_name,
1042 repo_context,
1043 exploration_depth,
1044 include_tests,
1045 if include_tests == "true" {
1046 "\n7. **Test Coverage**:\n - Existing test files and test cases\n - Test coverage analysis\n - Test quality and completeness\n - Missing test scenarios"
1047 } else {
1048 ""
1049 }
1050 );
1051
1052 Ok(GetPromptResult {
1053 description: Some("Comprehensive feature exploration and analysis".to_string()),
1054 messages: vec![PromptMessage {
1055 role: "user".to_string(),
1056 content: PromptContent::Text { text: prompt_text },
1057 }],
1058 })
1059 }
1060
1061 async fn learning_path_generator_prompt(
1063 &self,
1064 server: &CodePrismMcpServer,
1065 arguments: Option<serde_json::Map<String, Value>>,
1066 ) -> Result<GetPromptResult> {
1067 let learning_goal = arguments
1068 .as_ref()
1069 .and_then(|args| args.get("learning_goal"))
1070 .and_then(|v| v.as_str())
1071 .ok_or_else(|| anyhow::anyhow!("learning_goal argument is required"))?;
1072
1073 let current_knowledge = arguments
1074 .as_ref()
1075 .and_then(|args| args.get("current_knowledge"))
1076 .and_then(|v| v.as_str())
1077 .unwrap_or("beginner");
1078
1079 let time_constraint = arguments
1080 .as_ref()
1081 .and_then(|args| args.get("time_constraint"))
1082 .and_then(|v| v.as_str())
1083 .unwrap_or("1-week");
1084
1085 let repo_context = if let Some(repo_path) = server.repository_path() {
1086 format!("Repository: {}", repo_path.display())
1087 } else {
1088 "No repository currently loaded".to_string()
1089 };
1090
1091 let prompt_text = format!(
1092 r#"Please create a personalized learning path for the following goal:
1093
1094**Learning Goal**: {}
1095**Current Knowledge Level**: {}
1096**Time Available**: {}
1097**Repository Context**: {}
1098
1099Please create a structured learning path that includes:
1100
11011. **Learning Objectives**:
1102 - Specific, measurable goals
1103 - Prerequisites and assumptions
1104 - Success criteria
1105
11062. **Phased Learning Plan**:
1107 - Phase 1: Foundation (understanding basics)
1108 - Phase 2: Core Concepts (deeper understanding)
1109 - Phase 3: Advanced Topics (mastery and application)
1110 - Phase 4: Practical Application (hands-on work)
1111
11123. **Daily/Weekly Schedule**:
1113 - Time allocation for each phase
1114 - Daily learning tasks
1115 - Milestone checkpoints
1116
11174. **Resource Identification**:
1118 - Key files to study (prioritized list)
1119 - Important functions/classes to understand
1120 - Relevant documentation and comments
1121 - External resources if needed
1122
11235. **Hands-on Exercises**:
1124 - Specific code reading exercises
1125 - Small modification tasks
1126 - Debugging exercises
1127 - Code tracing activities
1128
11296. **Assessment Methods**:
1130 - Self-assessment questions
1131 - Practical challenges
1132 - Code review criteria
1133
11347. **Common Pitfalls and Tips**:
1135 - Areas that are typically confusing
1136 - Best practices to follow
1137 - Debugging strategies
1138
1139Use repository analysis tools to:
1140- Identify the most relevant files and functions for the learning goal
1141- Map dependencies and relationships
1142- Assess code complexity to sequence learning appropriately
1143- Find examples and test cases
1144
1145Adjust the complexity and pace based on the current knowledge level and time constraints."#,
1146 learning_goal, current_knowledge, time_constraint, repo_context
1147 );
1148
1149 Ok(GetPromptResult {
1150 description: Some("Personalized learning path through the codebase".to_string()),
1151 messages: vec![PromptMessage {
1152 role: "user".to_string(),
1153 content: PromptContent::Text { text: prompt_text },
1154 }],
1155 })
1156 }
1157
1158 async fn technology_stack_analysis_prompt(
1160 &self,
1161 server: &CodePrismMcpServer,
1162 arguments: Option<serde_json::Map<String, Value>>,
1163 ) -> Result<GetPromptResult> {
1164 let analysis_focus = arguments
1165 .as_ref()
1166 .and_then(|args| args.get("analysis_focus"))
1167 .and_then(|v| v.as_str())
1168 .unwrap_or("comprehensive");
1169
1170 let include_alternatives = arguments
1171 .as_ref()
1172 .and_then(|args| args.get("include_alternatives"))
1173 .and_then(|v| v.as_str())
1174 .unwrap_or("false");
1175
1176 let repo_context = if let Some(repo_path) = server.repository_path() {
1177 format!("Repository: {}", repo_path.display())
1178 } else {
1179 "No repository currently loaded".to_string()
1180 };
1181
1182 let prompt_text = format!(
1183 r#"Please analyze the technology stack and architectural decisions in this codebase:
1184
1185{}
1186
1187Analysis focus: {}
1188Include alternatives: {}
1189
1190Please provide a comprehensive analysis covering:
1191
11921. **Programming Languages**:
1193 - Primary and secondary languages used
1194 - Language versions and compatibility
1195 - Language-specific patterns and idioms
1196
11972. **Frameworks and Libraries**:
1198 - Web frameworks (if applicable)
1199 - Testing frameworks
1200 - Utility libraries and their purposes
1201 - Version information and update status
1202
12033. **Development Tools**:
1204 - Build systems and task runners
1205 - Package managers and dependency management
1206 - Code quality tools (linters, formatters)
1207 - Development environment setup
1208
12094. **Infrastructure and Deployment**:
1210 - Deployment strategies and tools
1211 - Containerization (Docker, etc.)
1212 - CI/CD pipeline tools
1213 - Cloud services and platforms
1214
12155. **Data Storage and Management**:
1216 - Database technologies
1217 - Data modeling approaches
1218 - Caching strategies
1219 - Data migration tools
1220
12216. **Architecture Patterns**:
1222 - Architectural styles (MVC, microservices, etc.)
1223 - Design patterns in use
1224 - Communication patterns (REST, GraphQL, etc.)
1225 - Event handling and messaging
1226
12277. **Security Technologies**:
1228 - Authentication and authorization frameworks
1229 - Security libraries and tools
1230 - Encryption and hashing methods
1231
12328. **Performance and Monitoring**:
1233 - Performance monitoring tools
1234 - Logging frameworks
1235 - Metrics and analytics tools
1236
1237{}
1238
12399. **Technology Assessment**:
1240 - Strengths of current technology choices
1241 - Potential limitations or technical debt
1242 - Compatibility and integration concerns
1243 - Maintenance and support considerations
1244
124510. **Recommendations**:
1246 - Technology upgrade suggestions
1247 - Missing tools or frameworks
1248 - Best practices alignment
1249 - Future-proofing considerations
1250
1251Use repository analysis tools to:
1252- Examine configuration files (package.json, requirements.txt, etc.)
1253- Analyze import statements and dependencies
1254- Review build and deployment scripts
1255- Assess code patterns and conventions
1256
1257Provide specific examples and file references where relevant."#,
1258 repo_context,
1259 analysis_focus,
1260 include_alternatives,
1261 if include_alternatives == "true" {
1262 "\n8. **Alternative Technology Considerations**:\n - Alternative frameworks or libraries\n - Trade-offs and migration considerations\n - Emerging technologies relevant to the project\n - Cost-benefit analysis of alternatives"
1263 } else {
1264 ""
1265 }
1266 );
1267
1268 Ok(GetPromptResult {
1269 description: Some("Comprehensive technology stack analysis".to_string()),
1270 messages: vec![PromptMessage {
1271 role: "user".to_string(),
1272 content: PromptContent::Text { text: prompt_text },
1273 }],
1274 })
1275 }
1276
1277 async fn codebase_health_check_prompt(
1279 &self,
1280 server: &CodePrismMcpServer,
1281 arguments: Option<serde_json::Map<String, Value>>,
1282 ) -> Result<GetPromptResult> {
1283 let health_aspects = arguments
1284 .as_ref()
1285 .and_then(|args| args.get("health_aspects"))
1286 .and_then(|v| v.as_str())
1287 .unwrap_or("comprehensive");
1288
1289 let severity_threshold = arguments
1290 .as_ref()
1291 .and_then(|args| args.get("severity_threshold"))
1292 .and_then(|v| v.as_str())
1293 .unwrap_or("medium");
1294
1295 let repo_context = if let Some(repo_path) = server.repository_path() {
1296 format!("Repository: {}", repo_path.display())
1297 } else {
1298 "No repository currently loaded".to_string()
1299 };
1300
1301 let prompt_text = format!(
1302 r#"Please perform a comprehensive health assessment of this codebase:
1303
1304{}
1305
1306Health aspects to focus on: {}
1307Minimum severity threshold: {}
1308
1309Please analyze and provide:
1310
13111. **Code Quality Metrics**:
1312 - Code complexity analysis (cyclomatic, cognitive)
1313 - Code duplication detection
1314 - Code style and consistency
1315 - Documentation coverage
1316
13172. **Maintainability Assessment**:
1318 - Code organization and structure
1319 - Naming conventions and clarity
1320 - Function and class size appropriateness
1321 - Coupling and cohesion analysis
1322
13233. **Technical Debt Analysis**:
1324 - Identified code smells and anti-patterns
1325 - Legacy code sections requiring attention
1326 - Architecture inconsistencies
1327 - Performance bottlenecks
1328
13294. **Security Assessment**:
1330 - Security vulnerability scan
1331 - Authentication and authorization review
1332 - Data handling and privacy concerns
1333 - Dependency security analysis
1334
13355. **Test Coverage and Quality**:
1336 - Test coverage percentage and gaps
1337 - Test quality and effectiveness
1338 - Test maintenance issues
1339 - Testing strategy evaluation
1340
13416. **Dependency Management**:
1342 - Outdated dependencies and security risks
1343 - Dependency conflicts and compatibility
1344 - Unused dependencies
1345 - License compliance review
1346
13477. **Performance Indicators**:
1348 - Performance hot spots and bottlenecks
1349 - Memory usage patterns
1350 - Algorithmic complexity issues
1351 - Scalability concerns
1352
13538. **Documentation Health**:
1354 - API documentation completeness
1355 - Code comment quality and coverage
1356 - Architecture documentation
1357 - User and developer guides
1358
13599. **Development Process Health**:
1360 - Build system reliability
1361 - CI/CD pipeline effectiveness
1362 - Code review practices
1363 - Version control hygiene
1364
136510. **Overall Health Score**:
1366 - Weighted health score (0-100)
1367 - Critical issues requiring immediate attention
1368 - Priority improvement recommendations
1369 - Long-term health strategy
1370
1371Use repository analysis tools to:
1372- Calculate complexity metrics
1373- Detect code duplicates and patterns
1374- Analyze dependencies and vulnerabilities
1375- Assess test coverage and quality
1376- Examine security patterns
1377
1378Provide specific examples, file paths, and actionable recommendations.
1379Focus on issues at or above the '{}' severity threshold."#,
1380 repo_context, health_aspects, severity_threshold, severity_threshold
1381 );
1382
1383 Ok(GetPromptResult {
1384 description: Some("Comprehensive codebase health assessment".to_string()),
1385 messages: vec![PromptMessage {
1386 role: "user".to_string(),
1387 content: PromptContent::Text { text: prompt_text },
1388 }],
1389 })
1390 }
1391
1392 async fn documentation_generator_prompt(
1394 &self,
1395 server: &CodePrismMcpServer,
1396 arguments: Option<serde_json::Map<String, Value>>,
1397 ) -> Result<GetPromptResult> {
1398 let documentation_type = arguments
1399 .as_ref()
1400 .and_then(|args| args.get("documentation_type"))
1401 .and_then(|v| v.as_str())
1402 .ok_or_else(|| anyhow::anyhow!("documentation_type argument is required"))?;
1403
1404 let target_audience = arguments
1405 .as_ref()
1406 .and_then(|args| args.get("target_audience"))
1407 .and_then(|v| v.as_str())
1408 .unwrap_or("developers");
1409
1410 let scope = arguments
1411 .as_ref()
1412 .and_then(|args| args.get("scope"))
1413 .and_then(|v| v.as_str())
1414 .unwrap_or("full_repository");
1415
1416 let repo_context = if let Some(repo_path) = server.repository_path() {
1417 format!("Repository: {}", repo_path.display())
1418 } else {
1419 "No repository currently loaded".to_string()
1420 };
1421
1422 let (doc_sections, specific_guidance) = match documentation_type {
1423 "API" => (
1424 vec![
1425 "API Overview and Purpose",
1426 "Authentication and Authorization",
1427 "Endpoint Documentation",
1428 "Request/Response Schemas",
1429 "Error Handling",
1430 "Rate Limiting and Pagination",
1431 "Code Examples and SDKs",
1432 "Versioning and Compatibility"
1433 ],
1434 "Focus on public APIs, endpoints, data models, and integration examples. Include OpenAPI/Swagger specs if applicable."
1435 ),
1436 "architecture" => (
1437 vec![
1438 "System Overview and Context",
1439 "Architecture Diagrams",
1440 "Component Descriptions",
1441 "Data Flow and Interactions",
1442 "Design Patterns and Principles",
1443 "Technology Stack",
1444 "Deployment Architecture",
1445 "Security Architecture"
1446 ],
1447 "Focus on high-level system design, component interactions, and architectural decisions."
1448 ),
1449 "developer_guide" => (
1450 vec![
1451 "Getting Started Guide",
1452 "Development Environment Setup",
1453 "Project Structure",
1454 "Coding Standards and Guidelines",
1455 "Build and Deployment Process",
1456 "Testing Guidelines",
1457 "Debugging and Troubleshooting",
1458 "Contributing Guidelines"
1459 ],
1460 "Focus on practical information for developers working on the codebase."
1461 ),
1462 "user_manual" => (
1463 vec![
1464 "Introduction and Overview",
1465 "Installation Instructions",
1466 "Basic Usage and Tutorials",
1467 "Feature Documentation",
1468 "Configuration Options",
1469 "Troubleshooting Guide",
1470 "FAQ and Common Issues",
1471 "Support and Resources"
1472 ],
1473 "Focus on end-user perspective, practical usage, and problem-solving."
1474 ),
1475 _ => (
1476 vec![
1477 "Project Overview",
1478 "Architecture and Design",
1479 "API Documentation",
1480 "Development Guide",
1481 "User Instructions"
1482 ],
1483 "Provide comprehensive documentation covering all aspects."
1484 )
1485 };
1486
1487 let sections_text = doc_sections
1488 .iter()
1489 .enumerate()
1490 .map(|(i, section)| format!("{}. **{}**", i + 1, section))
1491 .collect::<Vec<_>>()
1492 .join("\n ");
1493
1494 let prompt_text = format!(
1495 r#"Please generate comprehensive {} documentation for this codebase:
1496
1497{}
1498
1499Documentation type: {}
1500Target audience: {}
1501Scope: {}
1502
1503Please create documentation with the following structure:
1504
1505 {}
1506
1507**Specific Guidance**: {}
1508
1509**Documentation Requirements**:
1510- Clear, concise, and well-structured content
1511- Appropriate level of technical detail for the target audience
1512- Code examples and practical usage scenarios
1513- Visual aids where helpful (diagrams, flowcharts)
1514- Cross-references and navigation aids
1515- Up-to-date and accurate information
1516
1517**Content Guidelines**:
1518- Use clear headings and subheadings
1519- Include table of contents for longer documents
1520- Provide code examples with explanations
1521- Include troubleshooting sections where relevant
1522- Add links to related resources
1523- Use consistent formatting and style
1524
1525Use repository analysis tools to:
1526- Examine code structure and organization
1527- Extract API definitions and schemas
1528- Analyze dependencies and integrations
1529- Review existing documentation and comments
1530- Understand data models and interfaces
1531- Identify key features and functionalities
1532
1533Ensure the documentation is:
1534- Accurate and reflects the current codebase
1535- Complete within the specified scope
1536- Appropriately detailed for the target audience
1537- Professionally formatted and easy to navigate
1538- Include specific file paths and code references where helpful"#,
1539 documentation_type,
1540 repo_context,
1541 documentation_type,
1542 target_audience,
1543 scope,
1544 sections_text,
1545 specific_guidance
1546 );
1547
1548 Ok(GetPromptResult {
1549 description: Some(format!(
1550 "Generate {} documentation for {}",
1551 documentation_type, target_audience
1552 )),
1553 messages: vec![PromptMessage {
1554 role: "user".to_string(),
1555 content: PromptContent::Text { text: prompt_text },
1556 }],
1557 })
1558 }
1559
1560 async fn testing_strategy_analysis_prompt(
1562 &self,
1563 server: &CodePrismMcpServer,
1564 arguments: Option<serde_json::Map<String, Value>>,
1565 ) -> Result<GetPromptResult> {
1566 let test_types = arguments
1567 .as_ref()
1568 .and_then(|args| args.get("test_types"))
1569 .and_then(|v| v.as_str())
1570 .unwrap_or("comprehensive");
1571
1572 let coverage_threshold = arguments
1573 .as_ref()
1574 .and_then(|args| args.get("coverage_threshold"))
1575 .and_then(|v| v.as_str())
1576 .unwrap_or("80");
1577
1578 let repo_context = if let Some(repo_path) = server.repository_path() {
1579 format!("Repository: {}", repo_path.display())
1580 } else {
1581 "No repository currently loaded".to_string()
1582 };
1583
1584 let prompt_text = format!(
1585 r#"Please analyze the current testing strategy and provide recommendations for improvement:
1586
1587{}
1588
1589Test types to analyze: {}
1590Target coverage threshold: {}%
1591
1592Please provide a comprehensive testing analysis:
1593
15941. **Current Testing Overview**:
1595 - Existing test files and structure
1596 - Testing frameworks and tools in use
1597 - Test types currently implemented
1598 - Overall test coverage statistics
1599
16002. **Test Coverage Analysis**:
1601 - Line coverage, branch coverage, function coverage
1602 - Coverage gaps and untested areas
1603 - Critical paths without adequate testing
1604 - High-risk areas requiring more tests
1605
16063. **Test Quality Assessment**:
1607 - Test case effectiveness and completeness
1608 - Test maintenance and readability
1609 - Test data management and setup
1610 - Assertion quality and specificity
1611
16124. **Testing Strategy Evaluation**:
1613 - Unit testing strategy and coverage
1614 - Integration testing approach
1615 - End-to-end testing implementation
1616 - Performance and load testing
1617 - Security testing considerations
1618
16195. **Test Organization and Structure**:
1620 - Test file organization and naming
1621 - Test helper utilities and shared code
1622 - Test configuration and environment setup
1623 - Test data management strategies
1624
16256. **Testing Tools and Infrastructure**:
1626 - Testing framework effectiveness
1627 - CI/CD integration and automation
1628 - Test reporting and metrics
1629 - Test environment management
1630
16317. **Testing Best Practices Compliance**:
1632 - Test isolation and independence
1633 - Test naming and documentation
1634 - Mock and stub usage
1635 - Test pyramid adherence
1636
16378. **Identified Issues and Gaps**:
1638 - Missing test scenarios
1639 - Flaky or unreliable tests
1640 - Slow or inefficient tests
1641 - Maintenance bottlenecks
1642
16439. **Improvement Recommendations**:
1644 - Prioritized list of testing improvements
1645 - New test types to implement
1646 - Testing tool upgrades or changes
1647 - Process and workflow improvements
1648
164910. **Implementation Roadmap**:
1650 - Short-term quick wins
1651 - Medium-term strategic improvements
1652 - Long-term testing vision
1653 - Resource and time estimates
1654
1655Use repository analysis tools to:
1656- Identify all test files and patterns
1657- Analyze test coverage and gaps
1658- Examine testing frameworks and dependencies
1659- Review test organization and structure
1660- Assess test complexity and maintainability
1661
1662Provide specific examples, file paths, and actionable recommendations to reach the {}% coverage threshold."#,
1663 repo_context, test_types, coverage_threshold, coverage_threshold
1664 );
1665
1666 Ok(GetPromptResult {
1667 description: Some(
1668 "Comprehensive testing strategy analysis and recommendations".to_string(),
1669 ),
1670 messages: vec![PromptMessage {
1671 role: "user".to_string(),
1672 content: PromptContent::Text { text: prompt_text },
1673 }],
1674 })
1675 }
1676
1677 async fn migration_planning_prompt(
1679 &self,
1680 server: &CodePrismMcpServer,
1681 arguments: Option<serde_json::Map<String, Value>>,
1682 ) -> Result<GetPromptResult> {
1683 let migration_type = arguments
1684 .as_ref()
1685 .and_then(|args| args.get("migration_type"))
1686 .and_then(|v| v.as_str())
1687 .ok_or_else(|| anyhow::anyhow!("migration_type argument is required"))?;
1688
1689 let target_technology = arguments
1690 .as_ref()
1691 .and_then(|args| args.get("target_technology"))
1692 .and_then(|v| v.as_str())
1693 .unwrap_or("not specified");
1694
1695 let risk_tolerance = arguments
1696 .as_ref()
1697 .and_then(|args| args.get("risk_tolerance"))
1698 .and_then(|v| v.as_str())
1699 .unwrap_or("medium");
1700
1701 let repo_context = if let Some(repo_path) = server.repository_path() {
1702 format!("Repository: {}", repo_path.display())
1703 } else {
1704 "No repository currently loaded".to_string()
1705 };
1706
1707 let (migration_focus, specific_considerations) = match migration_type {
1708 "framework_upgrade" => (
1709 "Framework Version Upgrade",
1710 "Focus on breaking changes, deprecated features, and compatibility issues.",
1711 ),
1712 "language_migration" => (
1713 "Programming Language Migration",
1714 "Focus on language differences, ecosystem changes, and tooling requirements.",
1715 ),
1716 "architecture_change" => (
1717 "Architectural Transformation",
1718 "Focus on structural changes, component redesign, and system interactions.",
1719 ),
1720 _ => (
1721 "General Migration",
1722 "Focus on identifying migration requirements and planning approach.",
1723 ),
1724 };
1725
1726 let prompt_text = format!(
1727 r#"Please create a comprehensive migration plan for this {} project:
1728
1729{}
1730
1731Migration type: {}
1732Target technology: {}
1733Risk tolerance: {}
1734
1735**Migration Planning Overview**:
1736{}
1737
1738Please provide a detailed migration strategy:
1739
17401. **Current State Analysis**:
1741 - Current technology stack and versions
1742 - Dependencies and external integrations
1743 - Code structure and architectural patterns
1744 - Technical debt and legacy components
1745
17462. **Target State Definition**:
1747 - Target technology specifications
1748 - Expected benefits and improvements
1749 - New capabilities and features
1750 - Performance and scalability goals
1751
17523. **Gap Analysis**:
1753 - Compatibility issues and breaking changes
1754 - Features that need redesign or rewriting
1755 - Dependencies requiring updates or replacements
1756 - Infrastructure and tooling changes needed
1757
17584. **Migration Strategy**:
1759 - Recommended migration approach (big bang, incremental, parallel)
1760 - Migration phases and milestones
1761 - Rollback and contingency plans
1762 - Success criteria and validation methods
1763
17645. **Risk Assessment and Mitigation**:
1765 - Technical risks and challenges
1766 - Business continuity considerations
1767 - Resource and timeline risks
1768 - Mitigation strategies for each risk
1769
17706. **Implementation Roadmap**:
1771 - Phase-by-phase implementation plan
1772 - Timeline estimates and dependencies
1773 - Resource requirements and team structure
1774 - Key decision points and checkpoints
1775
17767. **Code Migration Planning**:
1777 - Files and modules requiring changes
1778 - Automated migration tools and scripts
1779 - Manual migration requirements
1780 - Code review and testing strategies
1781
17828. **Testing and Validation**:
1783 - Migration testing strategy
1784 - Regression testing approach
1785 - Performance testing requirements
1786 - User acceptance testing plan
1787
17889. **Deployment and Rollout**:
1789 - Deployment strategy and environments
1790 - Feature flags and gradual rollout
1791 - Monitoring and observability
1792 - Communication and training plans
1793
179410. **Post-Migration Considerations**:
1795 - Cleanup and optimization tasks
1796 - Documentation updates
1797 - Team training and knowledge transfer
1798 - Long-term maintenance considerations
1799
1800Use repository analysis tools to:
1801- Examine current codebase structure and dependencies
1802- Identify migration complexity and effort
1803- Assess code quality and technical debt
1804- Analyze testing coverage and quality
1805- Review architecture and design patterns
1806
1807Tailor recommendations to the {} risk tolerance level.
1808Provide specific file references, code examples, and actionable steps."#,
1809 migration_focus,
1810 repo_context,
1811 migration_type,
1812 target_technology,
1813 risk_tolerance,
1814 specific_considerations,
1815 risk_tolerance
1816 );
1817
1818 Ok(GetPromptResult {
1819 description: Some(format!(
1820 "Comprehensive migration planning for {}",
1821 migration_type
1822 )),
1823 messages: vec![PromptMessage {
1824 role: "user".to_string(),
1825 content: PromptContent::Text { text: prompt_text },
1826 }],
1827 })
1828 }
1829}
1830
1831#[cfg(test)]
1832mod tests {
1833 use super::*;
1834
1835 #[test]
1836 fn test_prompt_capabilities() {
1837 let capabilities = PromptCapabilities {
1838 list_changed: Some(false),
1839 };
1840
1841 assert_eq!(capabilities.list_changed, Some(false));
1842 }
1843
1844 #[test]
1845 fn test_prompt_serialization() {
1846 let prompt = Prompt {
1847 name: "test_prompt".to_string(),
1848 title: Some("Test Prompt".to_string()),
1849 description: "A test prompt".to_string(),
1850 arguments: Some(vec![PromptArgument {
1851 name: "test_arg".to_string(),
1852 description: "A test argument".to_string(),
1853 required: true,
1854 }]),
1855 };
1856
1857 let json = serde_json::to_string(&prompt).unwrap();
1858 let deserialized: Prompt = serde_json::from_str(&json).unwrap();
1859
1860 assert_eq!(prompt.name, deserialized.name);
1861 assert_eq!(prompt.title, deserialized.title);
1862 assert_eq!(prompt.description, deserialized.description);
1863 }
1864
1865 #[test]
1866 fn test_prompt_content_text() {
1867 let content = PromptContent::Text {
1868 text: "Hello, world!".to_string(),
1869 };
1870
1871 let json = serde_json::to_string(&content).unwrap();
1872 let deserialized: PromptContent = serde_json::from_str(&json).unwrap();
1873
1874 match deserialized {
1875 PromptContent::Text { text } => assert_eq!(text, "Hello, world!"),
1876 _ => panic!("Expected text content"),
1877 }
1878 }
1879
1880 async fn create_test_server() -> crate::CodePrismMcpServer {
1881 use std::fs;
1882 use tempfile::TempDir;
1883
1884 let temp_dir = TempDir::new().expect("Failed to create temp dir");
1885 let repo_path = temp_dir.path();
1886
1887 fs::write(
1889 repo_path.join("main.py"),
1890 r#"
1891class UserService:
1892 """Service for managing users."""
1893
1894 def __init__(self, database):
1895 self.database = database
1896
1897 def authenticate_user(self, username: str, password: str) -> bool:
1898 """Authenticate a user with username and password."""
1899 user = self.database.get_user(username)
1900 if not user:
1901 return False
1902 return user.verify_password(password)
1903
1904 def create_user(self, username: str, email: str, password: str) -> 'User':
1905 """Create a new user account."""
1906 if self.database.user_exists(username):
1907 raise ValueError("User already exists")
1908
1909 user = User(username, email, password)
1910 self.database.save_user(user)
1911 return user
1912
1913class User:
1914 """User model representing a system user."""
1915
1916 def __init__(self, username: str, email: str, password: str):
1917 self.username = username
1918 self.email = email
1919 self.password_hash = self._hash_password(password)
1920
1921 def verify_password(self, password: str) -> bool:
1922 """Verify the user's password."""
1923 return self._hash_password(password) == self.password_hash
1924
1925 def _hash_password(self, password: str) -> str:
1926 """Hash a password for storage."""
1927 import hashlib
1928 return hashlib.sha256(password.encode()).hexdigest()
1929"#,
1930 )
1931 .unwrap();
1932
1933 fs::write(
1934 repo_path.join("database.py"),
1935 r#"
1936"""Database interface for the application."""
1937
1938from typing import Optional, List
1939import sqlite3
1940
1941class Database:
1942 """Simple SQLite database interface."""
1943
1944 def __init__(self, db_path: str):
1945 self.db_path = db_path
1946 self.connection = sqlite3.connect(db_path)
1947 self._create_tables()
1948
1949 def _create_tables(self) -> None:
1950 """Create necessary database tables."""
1951 cursor = self.connection.cursor()
1952 cursor.execute('''
1953 CREATE TABLE IF NOT EXISTS users (
1954 id INTEGER PRIMARY KEY AUTOINCREMENT,
1955 username TEXT UNIQUE NOT NULL,
1956 email TEXT NOT NULL,
1957 password_hash TEXT NOT NULL
1958 )
1959 ''')
1960 self.connection.commit()
1961
1962 def get_user(self, username: str) -> Optional['User']:
1963 """Get a user by username."""
1964 cursor = self.connection.cursor()
1965 cursor.execute('SELECT * FROM users WHERE username = ?', (username,))
1966 row = cursor.fetchone()
1967
1968 if row:
1969 from main import User
1970 return User(row[1], row[2], "") # Password already hashed
1971 return None
1972
1973 def user_exists(self, username: str) -> bool:
1974 """Check if a user exists."""
1975 return self.get_user(username) is not None
1976
1977 def save_user(self, user: 'User') -> None:
1978 """Save a user to the database."""
1979 cursor = self.connection.cursor()
1980 cursor.execute(
1981 'INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)',
1982 (user.username, user.email, user.password_hash)
1983 )
1984 self.connection.commit()
1985"#,
1986 )
1987 .unwrap();
1988
1989 let mut server = crate::CodePrismMcpServer::new().expect("Failed to create server");
1990 server
1991 .initialize_with_repository(repo_path)
1992 .await
1993 .expect("Failed to initialize repository");
1994
1995 std::mem::forget(temp_dir);
1997
1998 server
1999 }
2000
2001 #[tokio::test]
2002 async fn test_prompt_manager_creation() {
2003 let server = create_test_server().await;
2004 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2005 let prompt_manager = PromptManager::new(server_arc);
2006
2007 }
2009
2010 #[tokio::test]
2011 async fn test_list_prompts() {
2012 let server = create_test_server().await;
2013 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2014 let prompt_manager = PromptManager::new(server_arc);
2015
2016 let result = prompt_manager
2017 .list_prompts(ListPromptsParams { cursor: None })
2018 .await;
2019 assert!(result.is_ok());
2020
2021 let prompts_result = result.unwrap();
2022 assert_eq!(prompts_result.prompts.len(), 16); assert!(prompts_result.next_cursor.is_none());
2024
2025 let prompt_names: Vec<String> = prompts_result
2027 .prompts
2028 .iter()
2029 .map(|p| p.name.clone())
2030 .collect();
2031 assert!(prompt_names.contains(&"repository_overview".to_string()));
2032 assert!(prompt_names.contains(&"code_analysis".to_string()));
2033 assert!(prompt_names.contains(&"debug_assistance".to_string()));
2034 assert!(prompt_names.contains(&"debug_issue".to_string()));
2035 assert!(prompt_names.contains(&"refactoring_guidance".to_string()));
2036
2037 for prompt in prompts_result.prompts {
2039 assert!(!prompt.name.is_empty());
2040 assert!(!prompt.description.is_empty());
2041
2042 if let Some(args) = prompt.arguments {
2044 for arg in args {
2045 assert!(!arg.name.is_empty());
2046 assert!(!arg.description.is_empty());
2047 }
2048 }
2049 }
2050 }
2051
2052 #[tokio::test]
2053 async fn test_repository_overview_prompt() {
2054 let server = create_test_server().await;
2055 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2056 let prompt_manager = PromptManager::new(server_arc);
2057
2058 let params = GetPromptParams {
2059 name: "repository_overview".to_string(),
2060 arguments: Some(serde_json::Map::from_iter([(
2061 "focus_area".to_string(),
2062 serde_json::Value::String("architecture".to_string()),
2063 )])),
2064 };
2065
2066 let result = prompt_manager.get_prompt(params).await;
2067 assert!(result.is_ok());
2068
2069 let prompt_result = result.unwrap();
2070 assert!(prompt_result.description.is_some());
2071 assert_eq!(prompt_result.messages.len(), 1);
2072
2073 let message = &prompt_result.messages[0];
2074 assert_eq!(message.role, "user");
2075
2076 if let PromptContent::Text { text } = &message.content {
2077 assert!(text.contains("architecture"));
2078 assert!(text.contains("repository"));
2079 assert!(text.contains("analyze"));
2080 } else {
2081 panic!("Expected text content");
2082 }
2083 }
2084
2085 #[tokio::test]
2086 async fn test_repository_overview_prompt_default_focus() {
2087 let server = create_test_server().await;
2088 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2089 let prompt_manager = PromptManager::new(server_arc);
2090
2091 let params = GetPromptParams {
2092 name: "repository_overview".to_string(),
2093 arguments: None, };
2095
2096 let result = prompt_manager.get_prompt(params).await;
2097 assert!(result.is_ok());
2098
2099 let prompt_result = result.unwrap();
2100 assert_eq!(prompt_result.messages.len(), 1);
2101
2102 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2103 assert!(text.contains("general")); }
2105 }
2106
2107 #[tokio::test]
2108 async fn test_code_analysis_prompt() {
2109 let server = create_test_server().await;
2110 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2111 let prompt_manager = PromptManager::new(server_arc);
2112
2113 let params = GetPromptParams {
2114 name: "code_analysis".to_string(),
2115 arguments: Some(serde_json::Map::from_iter([
2116 (
2117 "file_pattern".to_string(),
2118 serde_json::Value::String("*.py".to_string()),
2119 ),
2120 (
2121 "analysis_type".to_string(),
2122 serde_json::Value::String("security".to_string()),
2123 ),
2124 ])),
2125 };
2126
2127 let result = prompt_manager.get_prompt(params).await;
2128 assert!(result.is_ok());
2129
2130 let prompt_result = result.unwrap();
2131 assert_eq!(prompt_result.messages.len(), 1);
2132
2133 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2134 assert!(text.contains("security"));
2135 assert!(text.contains("*.py"));
2136 assert!(text.contains("analysis"));
2137 }
2138 }
2139
2140 #[tokio::test]
2141 async fn test_debug_assistance_prompt() {
2142 let server = create_test_server().await;
2143 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2144 let prompt_manager = PromptManager::new(server_arc);
2145
2146 let params = GetPromptParams {
2147 name: "debug_assistance".to_string(),
2148 arguments: Some(serde_json::Map::from_iter([
2149 (
2150 "issue_description".to_string(),
2151 serde_json::Value::String(
2152 "Authentication is failing for some users".to_string(),
2153 ),
2154 ),
2155 (
2156 "affected_files".to_string(),
2157 serde_json::Value::String("main.py, database.py".to_string()),
2158 ),
2159 ])),
2160 };
2161
2162 let result = prompt_manager.get_prompt(params).await;
2163 assert!(result.is_ok());
2164
2165 let prompt_result = result.unwrap();
2166 assert_eq!(prompt_result.messages.len(), 1);
2167
2168 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2169 assert!(text.contains("Authentication is failing"));
2170 assert!(text.contains("main.py, database.py"));
2171 assert!(text.contains("debugging"));
2172 }
2173 }
2174
2175 #[tokio::test]
2176 async fn test_debug_assistance_prompt_missing_required_arg() {
2177 let server = create_test_server().await;
2178 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2179 let prompt_manager = PromptManager::new(server_arc);
2180
2181 let params = GetPromptParams {
2182 name: "debug_assistance".to_string(),
2183 arguments: Some(serde_json::Map::from_iter([
2184 (
2185 "affected_files".to_string(),
2186 serde_json::Value::String("main.py".to_string()),
2187 ),
2188 ])),
2190 };
2191
2192 let result = prompt_manager.get_prompt(params).await;
2193 assert!(result.is_err());
2194
2195 let error = result.unwrap_err();
2196 assert!(error.to_string().contains("issue_description"));
2197 assert!(error.to_string().contains("required"));
2198 }
2199
2200 #[tokio::test]
2201 async fn test_debug_issue_prompt() {
2202 let server = create_test_server().await;
2203 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2204 let prompt_manager = PromptManager::new(server_arc);
2205
2206 let params = GetPromptParams {
2207 name: "debug_issue".to_string(),
2208 arguments: Some(serde_json::Map::from_iter([
2209 (
2210 "error_location".to_string(),
2211 serde_json::Value::String("main.py:25".to_string()),
2212 ),
2213 (
2214 "error_message".to_string(),
2215 serde_json::Value::String(
2216 "AttributeError: 'NoneType' object has no attribute 'verify_password'"
2217 .to_string(),
2218 ),
2219 ),
2220 ])),
2221 };
2222
2223 let result = prompt_manager.get_prompt(params).await;
2224 assert!(result.is_ok());
2225
2226 let prompt_result = result.unwrap();
2227 assert_eq!(prompt_result.messages.len(), 1);
2228
2229 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2230 assert!(text.contains("main.py:25"));
2231 assert!(text.contains("AttributeError"));
2232 assert!(text.contains("verify_password"));
2233 }
2234 }
2235
2236 #[tokio::test]
2237 async fn test_debug_issue_prompt_missing_required_arg() {
2238 let server = create_test_server().await;
2239 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2240 let prompt_manager = PromptManager::new(server_arc);
2241
2242 let params = GetPromptParams {
2243 name: "debug_issue".to_string(),
2244 arguments: Some(serde_json::Map::from_iter([
2245 (
2246 "error_message".to_string(),
2247 serde_json::Value::String("Some error".to_string()),
2248 ),
2249 ])),
2251 };
2252
2253 let result = prompt_manager.get_prompt(params).await;
2254 assert!(result.is_err());
2255
2256 let error = result.unwrap_err();
2257 assert!(error.to_string().contains("error_location"));
2258 assert!(error.to_string().contains("required"));
2259 }
2260
2261 #[tokio::test]
2262 async fn test_refactoring_guidance_prompt() {
2263 let server = create_test_server().await;
2264 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2265 let prompt_manager = PromptManager::new(server_arc);
2266
2267 let params = GetPromptParams {
2268 name: "refactoring_guidance".to_string(),
2269 arguments: Some(serde_json::Map::from_iter([
2270 (
2271 "target_area".to_string(),
2272 serde_json::Value::String("UserService class".to_string()),
2273 ),
2274 (
2275 "refactoring_goal".to_string(),
2276 serde_json::Value::String("improve testability".to_string()),
2277 ),
2278 ])),
2279 };
2280
2281 let result = prompt_manager.get_prompt(params).await;
2282 assert!(result.is_ok());
2283
2284 let prompt_result = result.unwrap();
2285 assert_eq!(prompt_result.messages.len(), 1);
2286
2287 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2288 assert!(text.contains("UserService class"));
2289 assert!(text.contains("improve testability"));
2290 assert!(text.contains("refactoring"));
2291 }
2292 }
2293
2294 #[tokio::test]
2295 async fn test_refactoring_guidance_prompt_missing_required_arg() {
2296 let server = create_test_server().await;
2297 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2298 let prompt_manager = PromptManager::new(server_arc);
2299
2300 let params = GetPromptParams {
2301 name: "refactoring_guidance".to_string(),
2302 arguments: Some(serde_json::Map::from_iter([
2303 (
2304 "refactoring_goal".to_string(),
2305 serde_json::Value::String("improve performance".to_string()),
2306 ),
2307 ])),
2309 };
2310
2311 let result = prompt_manager.get_prompt(params).await;
2312 assert!(result.is_err());
2313
2314 let error = result.unwrap_err();
2315 assert!(error.to_string().contains("target_area"));
2316 assert!(error.to_string().contains("required"));
2317 }
2318
2319 #[tokio::test]
2320 async fn test_unknown_prompt() {
2321 let server = create_test_server().await;
2322 let server_arc = std::sync::Arc::new(tokio::sync::RwLock::new(server));
2323 let prompt_manager = PromptManager::new(server_arc);
2324
2325 let params = GetPromptParams {
2326 name: "unknown_prompt".to_string(),
2327 arguments: None,
2328 };
2329
2330 let result = prompt_manager.get_prompt(params).await;
2331 assert!(result.is_err());
2332
2333 let error = result.unwrap_err();
2334 assert!(error.to_string().contains("Unknown prompt"));
2335 assert!(error.to_string().contains("unknown_prompt"));
2336 }
2337
2338 #[test]
2339 fn test_prompt_message_serialization() {
2340 let message = PromptMessage {
2341 role: "user".to_string(),
2342 content: PromptContent::Text {
2343 text: "Test message".to_string(),
2344 },
2345 };
2346
2347 let json = serde_json::to_string(&message).unwrap();
2348 let deserialized: PromptMessage = serde_json::from_str(&json).unwrap();
2349
2350 assert_eq!(message.role, deserialized.role);
2351 if let (PromptContent::Text { text: orig }, PromptContent::Text { text: deser }) =
2352 (&message.content, &deserialized.content)
2353 {
2354 assert_eq!(orig, deser);
2355 } else {
2356 panic!("Content type mismatch");
2357 }
2358 }
2359
2360 #[test]
2361 fn test_prompt_content_image() {
2362 let content = PromptContent::Image {
2363 data: "base64encodeddata".to_string(),
2364 mime_type: "image/png".to_string(),
2365 };
2366
2367 let json = serde_json::to_string(&content).unwrap();
2368 let deserialized: PromptContent = serde_json::from_str(&json).unwrap();
2369
2370 if let PromptContent::Image { data, mime_type } = deserialized {
2371 assert_eq!(data, "base64encodeddata");
2372 assert_eq!(mime_type, "image/png");
2373 } else {
2374 panic!("Expected image content");
2375 }
2376 }
2377
2378 #[test]
2379 fn test_get_prompt_params_serialization() {
2380 let mut arguments = serde_json::Map::new();
2381 arguments.insert(
2382 "key".to_string(),
2383 serde_json::Value::String("value".to_string()),
2384 );
2385
2386 let params = GetPromptParams {
2387 name: "test_prompt".to_string(),
2388 arguments: Some(arguments),
2389 };
2390
2391 let json = serde_json::to_string(¶ms).unwrap();
2392 let deserialized: GetPromptParams = serde_json::from_str(&json).unwrap();
2393
2394 assert_eq!(params.name, deserialized.name);
2395 assert_eq!(params.arguments, deserialized.arguments);
2396 }
2397
2398 #[test]
2399 fn test_get_prompt_result_serialization() {
2400 let result = GetPromptResult {
2401 description: Some("Test prompt result".to_string()),
2402 messages: vec![PromptMessage {
2403 role: "user".to_string(),
2404 content: PromptContent::Text {
2405 text: "Test content".to_string(),
2406 },
2407 }],
2408 };
2409
2410 let json = serde_json::to_string(&result).unwrap();
2411 let deserialized: GetPromptResult = serde_json::from_str(&json).unwrap();
2412
2413 assert_eq!(result.description, deserialized.description);
2414 assert_eq!(result.messages.len(), deserialized.messages.len());
2415 }
2416
2417 #[test]
2418 fn test_list_prompts_params_serialization() {
2419 let params = ListPromptsParams {
2420 cursor: Some("test_cursor".to_string()),
2421 };
2422
2423 let json = serde_json::to_string(¶ms).unwrap();
2424 let deserialized: ListPromptsParams = serde_json::from_str(&json).unwrap();
2425
2426 assert_eq!(params.cursor, deserialized.cursor);
2427 }
2428
2429 #[test]
2430 fn test_prompt_argument_serialization() {
2431 let arg = PromptArgument {
2432 name: "test_arg".to_string(),
2433 description: "Test argument".to_string(),
2434 required: true,
2435 };
2436
2437 let json = serde_json::to_value(&arg).unwrap();
2438 assert_eq!(json["name"], "test_arg");
2439 assert_eq!(json["description"], "Test argument");
2440 assert_eq!(json["required"], true);
2441
2442 let deserialized: PromptArgument = serde_json::from_value(json).unwrap();
2443 assert_eq!(deserialized.name, "test_arg");
2444 assert_eq!(deserialized.description, "Test argument");
2445 assert!(deserialized.required);
2446 }
2447
2448 #[tokio::test]
2449 async fn test_architectural_analysis_prompt() {
2450 let server = create_test_server().await;
2451 let prompt_manager =
2452 PromptManager::new(std::sync::Arc::new(tokio::sync::RwLock::new(server)));
2453
2454 let params = GetPromptParams {
2455 name: "architectural_analysis".to_string(),
2456 arguments: Some({
2457 let mut args = serde_json::Map::new();
2458 args.insert("analysis_focus".to_string(), "layers".into());
2459 args.insert("architectural_concerns".to_string(), "coupling".into());
2460 args
2461 }),
2462 };
2463
2464 let result = prompt_manager.get_prompt(params).await;
2465 assert!(result.is_ok());
2466
2467 let prompt_result = result.unwrap();
2468 assert!(prompt_result.description.is_some());
2469 assert_eq!(prompt_result.messages.len(), 1);
2470 assert_eq!(prompt_result.messages[0].role, "user");
2471
2472 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2473 assert!(text.contains("architectural"));
2474 assert!(text.contains("layers"));
2475 }
2476 }
2477
2478 #[tokio::test]
2479 async fn test_pattern_assessment_prompt() {
2480 let server = create_test_server().await;
2481 let prompt_manager =
2482 PromptManager::new(std::sync::Arc::new(tokio::sync::RwLock::new(server)));
2483
2484 let params = GetPromptParams {
2485 name: "pattern_assessment".to_string(),
2486 arguments: Some({
2487 let mut args = serde_json::Map::new();
2488 args.insert("pattern_types".to_string(), "design_patterns".into());
2489 args.insert("improvement_scope".to_string(), "immediate".into());
2490 args
2491 }),
2492 };
2493
2494 let result = prompt_manager.get_prompt(params).await;
2495 assert!(result.is_ok());
2496
2497 let prompt_result = result.unwrap();
2498 assert_eq!(prompt_result.messages.len(), 1);
2499
2500 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2501 assert!(text.contains("pattern"));
2502 assert!(text.contains("design_patterns"));
2503 }
2504 }
2505
2506 #[tokio::test]
2507 async fn test_dependency_analysis_prompt() {
2508 let server = create_test_server().await;
2509 let prompt_manager =
2510 PromptManager::new(std::sync::Arc::new(tokio::sync::RwLock::new(server)));
2511
2512 let params = GetPromptParams {
2513 name: "dependency_analysis".to_string(),
2514 arguments: Some({
2515 let mut args = serde_json::Map::new();
2516 args.insert("analysis_target".to_string(), "repository-wide".into());
2517 args.insert("dependency_concerns".to_string(), "cycles".into());
2518 args
2519 }),
2520 };
2521
2522 let result = prompt_manager.get_prompt(params).await;
2523 assert!(result.is_ok());
2524
2525 let prompt_result = result.unwrap();
2526 assert_eq!(prompt_result.messages.len(), 1);
2527
2528 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2529 assert!(text.contains("dependency"));
2530 assert!(text.contains("cycles"));
2531 }
2532 }
2533
2534 #[tokio::test]
2535 async fn test_new_prompts_in_list() {
2536 let server = create_test_server().await;
2537 let prompt_manager =
2538 PromptManager::new(std::sync::Arc::new(tokio::sync::RwLock::new(server)));
2539
2540 let params = ListPromptsParams { cursor: None };
2541 let result = prompt_manager.list_prompts(params).await;
2542 assert!(result.is_ok());
2543
2544 let prompts_result = result.unwrap();
2545 let prompt_names: Vec<&String> = prompts_result.prompts.iter().map(|p| &p.name).collect();
2546
2547 assert!(prompt_names.contains(&&"architectural_analysis".to_string()));
2549 assert!(prompt_names.contains(&&"pattern_assessment".to_string()));
2550 assert!(prompt_names.contains(&&"dependency_analysis".to_string()));
2551
2552 assert!(prompts_result.prompts.len() >= 16); }
2555
2556 #[tokio::test]
2557 async fn test_architectural_prompts_with_default_args() {
2558 let server = create_test_server().await;
2559 let prompt_manager =
2560 PromptManager::new(std::sync::Arc::new(tokio::sync::RwLock::new(server)));
2561
2562 let params = GetPromptParams {
2564 name: "architectural_analysis".to_string(),
2565 arguments: None,
2566 };
2567
2568 let result = prompt_manager.get_prompt(params).await;
2569 assert!(result.is_ok());
2570
2571 let prompt_result = result.unwrap();
2572 if let PromptContent::Text { text } = &prompt_result.messages[0].content {
2573 assert!(text.contains("general")); }
2575 }
2576
2577 #[tokio::test]
2578 async fn test_unknown_architectural_prompt() {
2579 let server = create_test_server().await;
2580 let prompt_manager =
2581 PromptManager::new(std::sync::Arc::new(tokio::sync::RwLock::new(server)));
2582
2583 let params = GetPromptParams {
2584 name: "unknown_architectural_prompt".to_string(),
2585 arguments: None,
2586 };
2587
2588 let result = prompt_manager.get_prompt(params).await;
2589 assert!(result.is_err()); }
2591}