1use anyhow::Result;
7use serde_json::{json, Value};
8
9use crate::context::session::SessionId;
10use crate::context::session::WorkflowStage;
11use crate::tools::{CallToolResult, Tool, ToolContent};
12use crate::CodePrismMcpServer;
13
14pub fn create_suggest_analysis_workflow_tool() -> Tool {
16 Tool {
17 name: "suggest_analysis_workflow".to_string(),
18 title: Some("Suggest Analysis Workflow".to_string()),
19 description: "Recommend optimal sequence of analysis tools based on user goals and current context. Provides systematic workflow guidance to achieve specific analysis objectives efficiently.".to_string(),
20 input_schema: json!({
21 "type": "object",
22 "properties": {
23 "goal": {
24 "type": "string",
25 "description": "Analysis objective: 'understand_codebase', 'find_security_issues', 'analyze_performance', 'trace_data_flow', 'analyze_architecture', 'debug_issue', 'refactor_preparation'"
26 },
27 "session_id": {
28 "type": "string",
29 "description": "Session ID for context-aware recommendations (optional)"
30 },
31 "complexity_preference": {
32 "type": "string",
33 "enum": ["quick", "standard", "comprehensive"],
34 "description": "Analysis depth preference",
35 "default": "standard"
36 },
37 "time_constraints": {
38 "type": "integer",
39 "description": "Approximate time budget in minutes (optional)",
40 "minimum": 5,
41 "maximum": 240
42 },
43 "current_context": {
44 "type": "object",
45 "description": "Current analysis context (optional)",
46 "properties": {
47 "symbols_analyzed": {
48 "type": "array",
49 "items": {"type": "string"},
50 "description": "Symbols already analyzed"
51 },
52 "areas_of_interest": {
53 "type": "array",
54 "items": {"type": "string"},
55 "description": "Specific areas, files, or patterns to focus on"
56 },
57 "known_issues": {
58 "type": "array",
59 "items": {"type": "string"},
60 "description": "Known issues or concerns to investigate"
61 }
62 }
63 }
64 },
65 "required": ["goal"],
66 "additionalProperties": false
67 }),
68 }
69}
70
71pub async fn suggest_analysis_workflow(
73 _server: &CodePrismMcpServer,
74 arguments: Option<&Value>,
75) -> Result<CallToolResult> {
76 let args = arguments.ok_or_else(|| anyhow::anyhow!("Missing arguments"))?;
77
78 let goal = args
79 .get("goal")
80 .and_then(|v| v.as_str())
81 .ok_or_else(|| anyhow::anyhow!("Missing or invalid goal parameter"))?;
82
83 let session_id = args
84 .get("session_id")
85 .and_then(|v| v.as_str())
86 .map(|s| SessionId(s.to_string()));
87
88 let complexity = args
89 .get("complexity_preference")
90 .and_then(|v| v.as_str())
91 .unwrap_or("standard");
92
93 let time_budget = args
94 .get("time_constraints")
95 .and_then(|v| v.as_u64())
96 .map(|t| t as u32);
97
98 let current_context = args.get("current_context");
99
100 let workflow = generate_workflow_for_goal(
102 goal,
103 complexity,
104 time_budget,
105 current_context,
106 session_id.as_ref(),
107 )?;
108
109 let mut result = json!({
111 "workflow_plan": {
112 "goal": goal,
113 "complexity_level": complexity,
114 "estimated_duration_minutes": workflow.estimated_duration,
115 "total_tools": workflow.tool_sequence.len(),
116 "workflow_stages": workflow.stages,
117 "success_criteria": workflow.success_criteria
118 },
119 "tool_sequence": workflow.tool_sequence,
120 "execution_strategy": {
121 "type": workflow.execution_type,
122 "parallel_groups": workflow.parallel_groups,
123 "dependencies": workflow.dependencies
124 },
125 "guidance": {
126 "getting_started": workflow.getting_started_guidance,
127 "optimization_tips": workflow.optimization_tips,
128 "common_pitfalls": workflow.common_pitfalls,
129 "alternative_approaches": workflow.alternative_approaches
130 }
131 });
132
133 if let Some(session_id) = session_id {
135 if let Ok(session_context) = get_session_context(session_id) {
136 result["session_context"] = json!({
137 "current_stage": session_context.current_stage,
138 "completed_tools": session_context.completed_tools,
139 "recommendations": session_context.recommendations,
140 "progress_assessment": session_context.progress_assessment
141 });
142 }
143 }
144
145 Ok(CallToolResult {
146 content: vec![ToolContent::Text {
147 text: serde_json::to_string_pretty(&result)?,
148 }],
149 is_error: Some(false),
150 })
151}
152
153#[derive(Debug, Clone)]
155struct WorkflowRecommendation {
156 _goal: String,
157 estimated_duration: u32,
158 tool_sequence: Vec<ToolStep>,
159 stages: Vec<WorkflowStageInfo>,
160 execution_type: String,
161 parallel_groups: Vec<Vec<String>>,
162 dependencies: Vec<ToolDependency>,
163 success_criteria: Vec<String>,
164 getting_started_guidance: String,
165 optimization_tips: Vec<String>,
166 common_pitfalls: Vec<String>,
167 alternative_approaches: Vec<String>,
168}
169
170#[derive(Debug, Clone, serde::Serialize)]
172struct ToolStep {
173 step: u32,
174 tool_name: String,
175 parameters: serde_json::Value,
176 reasoning: String,
177 expected_outcome: String,
178 estimated_time_minutes: u32,
179 priority: String,
180 optional: bool,
181}
182
183#[derive(Debug, Clone, serde::Serialize)]
185struct WorkflowStageInfo {
186 stage: String,
187 description: String,
188 tools: Vec<String>,
189 success_indicators: Vec<String>,
190}
191
192#[derive(Debug, Clone, serde::Serialize)]
194struct ToolDependency {
195 tool: String,
196 depends_on: Vec<String>,
197 dependency_type: String,
198}
199
200#[derive(Debug, Clone)]
202struct SessionContext {
203 current_stage: WorkflowStage,
204 completed_tools: Vec<String>,
205 recommendations: Vec<String>,
206 progress_assessment: String,
207}
208
209fn generate_workflow_for_goal(
211 goal: &str,
212 complexity: &str,
213 time_budget: Option<u32>,
214 _current_context: Option<&Value>,
215 _session_id: Option<&SessionId>,
216) -> Result<WorkflowRecommendation> {
217 match goal {
218 "understand_codebase" => generate_codebase_understanding_workflow(complexity, time_budget),
219 "find_security_issues" => generate_security_analysis_workflow(complexity, time_budget),
220 "analyze_performance" => generate_performance_analysis_workflow(complexity, time_budget),
221 "trace_data_flow" => generate_data_flow_analysis_workflow(complexity, time_budget),
222 "analyze_architecture" => generate_architecture_analysis_workflow(complexity, time_budget),
223 "debug_issue" => generate_debugging_workflow(complexity, time_budget),
224 "refactor_preparation" => generate_refactoring_workflow(complexity, time_budget),
225 _ => Err(anyhow::anyhow!("Unknown analysis goal: {}", goal)),
226 }
227}
228
229fn generate_codebase_understanding_workflow(
231 complexity: &str,
232 time_budget: Option<u32>,
233) -> Result<WorkflowRecommendation> {
234 let (tools, duration) = match complexity {
235 "quick" => (
236 vec![
237 ToolStep {
238 step: 1,
239 tool_name: "repository_stats".to_string(),
240 parameters: json!({}),
241 reasoning: "Get high-level overview of repository structure and metrics"
242 .to_string(),
243 expected_outcome: "Understanding of codebase size, languages, and organization"
244 .to_string(),
245 estimated_time_minutes: 2,
246 priority: "high".to_string(),
247 optional: false,
248 },
249 ToolStep {
250 step: 2,
251 tool_name: "search_symbols".to_string(),
252 parameters: json!({"pattern": ".*", "limit": 20}),
253 reasoning: "Discover main classes and functions in the codebase".to_string(),
254 expected_outcome: "List of key symbols and entry points".to_string(),
255 estimated_time_minutes: 3,
256 priority: "high".to_string(),
257 optional: false,
258 },
259 ],
260 10,
261 ),
262 "comprehensive" => (
263 vec![
264 ToolStep {
265 step: 1,
266 tool_name: "repository_stats".to_string(),
267 parameters: json!({}),
268 reasoning: "Get comprehensive repository metrics and structure analysis"
269 .to_string(),
270 expected_outcome: "Detailed understanding of codebase organization".to_string(),
271 estimated_time_minutes: 3,
272 priority: "high".to_string(),
273 optional: false,
274 },
275 ToolStep {
276 step: 2,
277 tool_name: "search_symbols".to_string(),
278 parameters: json!({"pattern": ".*", "limit": 50}),
279 reasoning: "Comprehensive symbol discovery and classification".to_string(),
280 expected_outcome: "Complete catalog of main symbols".to_string(),
281 estimated_time_minutes: 5,
282 priority: "high".to_string(),
283 optional: false,
284 },
285 ToolStep {
286 step: 3,
287 tool_name: "detect_patterns".to_string(),
288 parameters: json!({"pattern_types": ["architectural", "design"]}),
289 reasoning: "Identify architectural and design patterns in use".to_string(),
290 expected_outcome:
291 "Understanding of architectural patterns and design principles".to_string(),
292 estimated_time_minutes: 8,
293 priority: "medium".to_string(),
294 optional: false,
295 },
296 ToolStep {
297 step: 4,
298 tool_name: "analyze_transitive_dependencies".to_string(),
299 parameters: json!({"max_depth": 3}),
300 reasoning: "Analyze module dependencies and coupling".to_string(),
301 expected_outcome: "Dependency graph and coupling analysis".to_string(),
302 estimated_time_minutes: 10,
303 priority: "medium".to_string(),
304 optional: true,
305 },
306 ],
307 30,
308 ),
309 _ => (
310 vec![
312 ToolStep {
313 step: 1,
314 tool_name: "repository_stats".to_string(),
315 parameters: json!({}),
316 reasoning: "Get overview of repository structure and basic metrics".to_string(),
317 expected_outcome: "Understanding of codebase scope and organization"
318 .to_string(),
319 estimated_time_minutes: 2,
320 priority: "high".to_string(),
321 optional: false,
322 },
323 ToolStep {
324 step: 2,
325 tool_name: "search_symbols".to_string(),
326 parameters: json!({"pattern": ".*", "limit": 30}),
327 reasoning: "Discover key symbols and main components".to_string(),
328 expected_outcome: "Catalog of important classes and functions".to_string(),
329 estimated_time_minutes: 4,
330 priority: "high".to_string(),
331 optional: false,
332 },
333 ToolStep {
334 step: 3,
335 tool_name: "detect_patterns".to_string(),
336 parameters: json!({"pattern_types": ["architectural"]}),
337 reasoning: "Identify main architectural patterns".to_string(),
338 expected_outcome: "Understanding of architectural approach".to_string(),
339 estimated_time_minutes: 6,
340 priority: "medium".to_string(),
341 optional: false,
342 },
343 ],
344 20,
345 ),
346 };
347
348 let adjusted_duration = time_budget.unwrap_or(duration).min(duration);
349
350 Ok(WorkflowRecommendation {
351 _goal: "understand_codebase".to_string(),
352 estimated_duration: adjusted_duration,
353 tool_sequence: tools,
354 stages: vec![
355 WorkflowStageInfo {
356 stage: "Discovery".to_string(),
357 description: "Initial exploration and high-level understanding".to_string(),
358 tools: vec!["repository_stats".to_string()],
359 success_indicators: vec!["Repository metrics obtained".to_string()],
360 },
361 WorkflowStageInfo {
362 stage: "Mapping".to_string(),
363 description: "Symbol discovery and component identification".to_string(),
364 tools: vec!["search_symbols".to_string(), "detect_patterns".to_string()],
365 success_indicators: vec!["Key symbols identified".to_string(), "Patterns recognized".to_string()],
366 },
367 ],
368 execution_type: "sequential".to_string(),
369 parallel_groups: vec![],
370 dependencies: vec![
371 ToolDependency {
372 tool: "search_symbols".to_string(),
373 depends_on: vec!["repository_stats".to_string()],
374 dependency_type: "context".to_string(),
375 }
376 ],
377 success_criteria: vec![
378 "Repository structure and metrics understood".to_string(),
379 "Key symbols and components identified".to_string(),
380 "Architectural patterns recognized".to_string(),
381 ],
382 getting_started_guidance: "Start with repository_stats to get an overview, then use search_symbols to discover key components. Focus on understanding the overall structure before diving into details.".to_string(),
383 optimization_tips: vec![
384 "Use symbol search results to guide deeper analysis".to_string(),
385 "Pattern detection helps understand design principles".to_string(),
386 "Repository stats provide context for subsequent analysis".to_string(),
387 ],
388 common_pitfalls: vec![
389 "Don't get lost in details too early - maintain high-level perspective".to_string(),
390 "Repository stats should guide symbol search scope".to_string(),
391 ],
392 alternative_approaches: vec![
393 "Start with specific areas of interest if known".to_string(),
394 "Use search_content for text-based exploration".to_string(),
395 ],
396 })
397}
398
399fn generate_security_analysis_workflow(
401 complexity: &str,
402 time_budget: Option<u32>,
403) -> Result<WorkflowRecommendation> {
404 let base_duration = match complexity {
405 "quick" => 15,
406 "comprehensive" => 45,
407 _ => 25,
408 };
409
410 Ok(WorkflowRecommendation {
411 _goal: "find_security_issues".to_string(),
412 estimated_duration: time_budget.unwrap_or(base_duration),
413 tool_sequence: vec![ToolStep {
414 step: 1,
415 tool_name: "analyze_security".to_string(),
416 parameters: json!({"include_all_severities": true}),
417 reasoning: "Comprehensive security vulnerability scan".to_string(),
418 expected_outcome: "Identification of potential security issues".to_string(),
419 estimated_time_minutes: base_duration,
420 priority: "high".to_string(),
421 optional: false,
422 }],
423 stages: vec![WorkflowStageInfo {
424 stage: "Security Analysis".to_string(),
425 description: "Comprehensive security vulnerability assessment".to_string(),
426 tools: vec!["analyze_security".to_string()],
427 success_indicators: vec!["Security issues identified and prioritized".to_string()],
428 }],
429 execution_type: "sequential".to_string(),
430 parallel_groups: vec![],
431 dependencies: vec![],
432 success_criteria: vec!["Security vulnerabilities identified and assessed".to_string()],
433 getting_started_guidance:
434 "Run comprehensive security analysis to identify potential vulnerabilities".to_string(),
435 optimization_tips: vec!["Focus on high-severity issues first".to_string()],
436 common_pitfalls: vec!["Don't ignore low-severity issues in production code".to_string()],
437 alternative_approaches: vec![
438 "Combine with code pattern analysis for better context".to_string()
439 ],
440 })
441}
442
443fn generate_performance_analysis_workflow(
445 complexity: &str,
446 time_budget: Option<u32>,
447) -> Result<WorkflowRecommendation> {
448 let base_duration = match complexity {
449 "quick" => 10,
450 "comprehensive" => 30,
451 _ => 20,
452 };
453
454 Ok(WorkflowRecommendation {
455 _goal: "analyze_performance".to_string(),
456 estimated_duration: time_budget.unwrap_or(base_duration),
457 tool_sequence: vec![ToolStep {
458 step: 1,
459 tool_name: "analyze_performance".to_string(),
460 parameters: json!({}),
461 reasoning: "Analyze performance characteristics and bottlenecks".to_string(),
462 expected_outcome: "Performance issues and optimization opportunities identified"
463 .to_string(),
464 estimated_time_minutes: base_duration,
465 priority: "high".to_string(),
466 optional: false,
467 }],
468 stages: vec![WorkflowStageInfo {
469 stage: "Performance Analysis".to_string(),
470 description: "Performance bottleneck identification and optimization".to_string(),
471 tools: vec!["analyze_performance".to_string()],
472 success_indicators: vec!["Performance issues identified".to_string()],
473 }],
474 execution_type: "sequential".to_string(),
475 parallel_groups: vec![],
476 dependencies: vec![],
477 success_criteria: vec!["Performance bottlenecks identified and prioritized".to_string()],
478 getting_started_guidance:
479 "Analyze performance characteristics to identify optimization opportunities".to_string(),
480 optimization_tips: vec!["Focus on high-impact performance improvements".to_string()],
481 common_pitfalls: vec!["Don't optimize without measuring impact".to_string()],
482 alternative_approaches: vec![
483 "Combine with complexity analysis for comprehensive assessment".to_string(),
484 ],
485 })
486}
487
488fn generate_data_flow_analysis_workflow(
490 complexity: &str,
491 time_budget: Option<u32>,
492) -> Result<WorkflowRecommendation> {
493 let base_duration = match complexity {
494 "quick" => 12,
495 "comprehensive" => 35,
496 _ => 22,
497 };
498
499 Ok(WorkflowRecommendation {
500 _goal: "trace_data_flow".to_string(),
501 estimated_duration: time_budget.unwrap_or(base_duration),
502 tool_sequence: vec![ToolStep {
503 step: 1,
504 tool_name: "trace_data_flow".to_string(),
505 parameters: json!({"include_transformations": true}),
506 reasoning: "Trace data flow and transformations through the system".to_string(),
507 expected_outcome: "Understanding of data flow patterns and transformations".to_string(),
508 estimated_time_minutes: base_duration,
509 priority: "high".to_string(),
510 optional: false,
511 }],
512 stages: vec![WorkflowStageInfo {
513 stage: "Data Flow Analysis".to_string(),
514 description: "Comprehensive data flow tracing and analysis".to_string(),
515 tools: vec!["trace_data_flow".to_string()],
516 success_indicators: vec!["Data flow patterns identified".to_string()],
517 }],
518 execution_type: "sequential".to_string(),
519 parallel_groups: vec![],
520 dependencies: vec![],
521 success_criteria: vec!["Data flow and transformations mapped".to_string()],
522 getting_started_guidance: "Trace data flow to understand system data processing"
523 .to_string(),
524 optimization_tips: vec!["Focus on critical data paths first".to_string()],
525 common_pitfalls: vec!["Don't ignore error handling in data flow".to_string()],
526 alternative_approaches: vec![
527 "Use symbol analysis to understand data structures first".to_string()
528 ],
529 })
530}
531
532fn generate_architecture_analysis_workflow(
534 complexity: &str,
535 time_budget: Option<u32>,
536) -> Result<WorkflowRecommendation> {
537 let base_duration = match complexity {
538 "quick" => 15,
539 "comprehensive" => 40,
540 _ => 25,
541 };
542
543 Ok(WorkflowRecommendation {
544 _goal: "analyze_architecture".to_string(),
545 estimated_duration: time_budget.unwrap_or(base_duration),
546 tool_sequence: vec![ToolStep {
547 step: 1,
548 tool_name: "detect_patterns".to_string(),
549 parameters: json!({"pattern_types": ["architectural", "design"]}),
550 reasoning: "Identify architectural and design patterns".to_string(),
551 expected_outcome: "Architecture patterns and design principles understood".to_string(),
552 estimated_time_minutes: base_duration,
553 priority: "high".to_string(),
554 optional: false,
555 }],
556 stages: vec![WorkflowStageInfo {
557 stage: "Architecture Analysis".to_string(),
558 description: "Architectural pattern identification and analysis".to_string(),
559 tools: vec!["detect_patterns".to_string()],
560 success_indicators: vec!["Architecture patterns identified".to_string()],
561 }],
562 execution_type: "sequential".to_string(),
563 parallel_groups: vec![],
564 dependencies: vec![],
565 success_criteria: vec!["Architectural patterns and principles identified".to_string()],
566 getting_started_guidance: "Analyze architectural patterns to understand system design"
567 .to_string(),
568 optimization_tips: vec!["Focus on main architectural patterns first".to_string()],
569 common_pitfalls: vec![
570 "Don't confuse implementation patterns with architectural patterns".to_string(),
571 ],
572 alternative_approaches: vec![
573 "Use dependency analysis to understand component relationships".to_string(),
574 ],
575 })
576}
577
578fn generate_debugging_workflow(
580 complexity: &str,
581 time_budget: Option<u32>,
582) -> Result<WorkflowRecommendation> {
583 let base_duration = match complexity {
584 "quick" => 18,
585 "comprehensive" => 50,
586 _ => 30,
587 };
588
589 Ok(WorkflowRecommendation {
590 _goal: "debug_issue".to_string(),
591 estimated_duration: time_budget.unwrap_or(base_duration),
592 tool_sequence: vec![ToolStep {
593 step: 1,
594 tool_name: "search_symbols".to_string(),
595 parameters: json!({"pattern": ".*"}),
596 reasoning: "Find relevant symbols related to the issue".to_string(),
597 expected_outcome: "Relevant code components identified".to_string(),
598 estimated_time_minutes: base_duration,
599 priority: "high".to_string(),
600 optional: false,
601 }],
602 stages: vec![WorkflowStageInfo {
603 stage: "Issue Investigation".to_string(),
604 description: "Systematic debugging and issue analysis".to_string(),
605 tools: vec!["search_symbols".to_string()],
606 success_indicators: vec!["Issue-related code identified".to_string()],
607 }],
608 execution_type: "sequential".to_string(),
609 parallel_groups: vec![],
610 dependencies: vec![],
611 success_criteria: vec!["Issue location and cause identified".to_string()],
612 getting_started_guidance: "Start by identifying symbols related to the issue".to_string(),
613 optimization_tips: vec!["Use specific search terms related to the issue".to_string()],
614 common_pitfalls: vec!["Don't assume the issue is where it manifests".to_string()],
615 alternative_approaches: vec!["Use trace_data_flow if issue is data-related".to_string()],
616 })
617}
618
619fn generate_refactoring_workflow(
621 complexity: &str,
622 time_budget: Option<u32>,
623) -> Result<WorkflowRecommendation> {
624 let base_duration = match complexity {
625 "quick" => 20,
626 "comprehensive" => 60,
627 _ => 35,
628 };
629
630 Ok(WorkflowRecommendation {
631 _goal: "refactor_preparation".to_string(),
632 estimated_duration: time_budget.unwrap_or(base_duration),
633 tool_sequence: vec![ToolStep {
634 step: 1,
635 tool_name: "analyze_complexity".to_string(),
636 parameters: json!({}),
637 reasoning: "Identify complex code that needs refactoring".to_string(),
638 expected_outcome: "Complex code areas identified for refactoring".to_string(),
639 estimated_time_minutes: base_duration,
640 priority: "high".to_string(),
641 optional: false,
642 }],
643 stages: vec![WorkflowStageInfo {
644 stage: "Refactoring Analysis".to_string(),
645 description: "Code complexity analysis for refactoring planning".to_string(),
646 tools: vec!["analyze_complexity".to_string()],
647 success_indicators: vec!["Refactoring targets identified".to_string()],
648 }],
649 execution_type: "sequential".to_string(),
650 parallel_groups: vec![],
651 dependencies: vec![],
652 success_criteria: vec!["Refactoring opportunities identified and prioritized".to_string()],
653 getting_started_guidance: "Analyze code complexity to identify refactoring opportunities"
654 .to_string(),
655 optimization_tips: vec!["Focus on high-complexity, high-impact areas".to_string()],
656 common_pitfalls: vec!["Don't refactor without understanding current behavior".to_string()],
657 alternative_approaches: vec![
658 "Use duplicate detection to find refactoring opportunities".to_string()
659 ],
660 })
661}
662
663fn get_session_context(_session_id: SessionId) -> Result<SessionContext> {
665 Ok(SessionContext {
667 current_stage: WorkflowStage::Discovery,
668 completed_tools: vec![],
669 recommendations: vec!["Start with repository overview".to_string()],
670 progress_assessment: "Beginning analysis".to_string(),
671 })
672}