foundry_mcp/cli/commands/
validate_content.rs1use crate::cli::args::ValidateContentArgs;
7use crate::core::validation::{parse_content_type, validate_content};
8use crate::types::responses::{FoundryResponse, ValidateContentResponse, ValidationStatus};
9use anyhow::{Context, Result};
10
11fn validate_input_args(content_type: &str, content: &str) -> Result<()> {
13 if content_type.trim().is_empty() {
15 return Err(anyhow::anyhow!(
16 "Content type cannot be empty. Supported types: vision, tech-stack, summary, spec, notes, tasks"
17 ));
18 }
19
20 const MAX_VALIDATION_SIZE: usize = 100_000; if content.len() > MAX_VALIDATION_SIZE {
23 return Err(anyhow::anyhow!(
24 "Content too large for validation ({} characters). Maximum size for validation is {} characters.",
25 content.len(),
26 MAX_VALIDATION_SIZE
27 ));
28 }
29
30 if content.contains('\0') {
32 return Err(anyhow::anyhow!(
33 "Content appears to contain binary data. Only text content can be validated."
34 ));
35 }
36
37 Ok(())
38}
39
40pub async fn execute(
41 args: ValidateContentArgs,
42) -> Result<FoundryResponse<ValidateContentResponse>> {
43 validate_input_args(&args.content_type, &args.content)
45 .with_context(|| "Input validation failed")?;
46
47 let content_type = parse_content_type(&args.content_type)
49 .with_context(|| {
50 format!(
51 "Invalid content type '{}'. Supported types are: vision, tech-stack, summary, spec, notes, tasks",
52 args.content_type
53 )
54 })?;
55
56 let validation_result = validate_content(content_type, &args.content);
58
59 let response_data = ValidateContentResponse {
61 content_type: args.content_type.clone(),
62 is_valid: validation_result.is_valid,
63 validation_errors: validation_result.errors.clone(),
64 suggestions: validation_result.suggestions.clone(),
65 };
66
67 let validation_status = if validation_result.is_valid {
69 ValidationStatus::Complete } else {
71 ValidationStatus::Error
72 };
73
74 let next_steps = if validation_result.is_valid {
76 let mut steps =
77 vec!["Content validation passed - ready to use in project creation".to_string()];
78
79 if !validation_result.suggestions.is_empty() {
80 steps.push(format!(
81 "Consider incorporating {} suggestions to improve content quality",
82 validation_result.suggestions.len()
83 ));
84 }
85
86 steps.push("Use this content via MCP: {\"name\": \"create_project\", \"arguments\": {\"project_name\": \"<name>\", \"vision\": \"...\", \"tech_stack\": \"...\", \"summary\": \"...\"}} or {\"name\": \"analyze_project\", \"arguments\": {\"project_name\": \"<name>\", \"vision\": \"...\", \"tech_stack\": \"...\", \"summary\": \"...\"}}".to_string());
87 steps
88 } else {
89 let error_count = validation_result.errors.len();
90 let suggestion_count = validation_result.suggestions.len();
91
92 let mut steps = vec![format!(
93 "Fix {} validation error(s) before using this content",
94 error_count
95 )];
96
97 if suggestion_count > 0 {
98 steps.push(format!(
99 "Review {} suggestion(s) for improvement guidance",
100 suggestion_count
101 ));
102 }
103
104 steps.push("Re-run validation after making changes".to_string());
105 steps
106 };
107
108 let mut workflow_hints = vec![
110 "Use this command to pre-validate content before project operations".to_string(),
111 "Validation helps ensure content meets Foundry's structural requirements".to_string(),
112 ];
113
114 match args.content_type.as_str() {
116 "vision" => workflow_hints.push(
117 "Vision should describe the problem, target users, and value proposition".to_string(),
118 ),
119 "tech-stack" => workflow_hints.push(
120 "Tech stack should include languages, frameworks, and deployment decisions".to_string(),
121 ),
122 "summary" => workflow_hints
123 .push("Summary should be concise but capture key project insights".to_string()),
124 "spec" => workflow_hints.push(
125 "Spec should include clear requirements and functionality descriptions".to_string(),
126 ),
127 "notes" => workflow_hints
128 .push("Notes provide additional context and implementation considerations".to_string()),
129 "tasks" => workflow_hints
130 .push("Tasks should be actionable items with clear completion criteria".to_string()),
131 _ => workflow_hints
132 .push("Follow the content guidelines for your specific content type".to_string()),
133 }
134
135 workflow_hints
136 .push("Content validation is performed client-side for immediate feedback".to_string());
137
138 Ok(FoundryResponse {
139 data: response_data,
140 next_steps,
141 validation_status,
142 workflow_hints,
143 })
144}