helix_core/compiler/tools/
generate.rs

1use std::path::PathBuf;
2use std::fs;
3use anyhow::{Result, Context};
4pub fn generate_code(
5    template: String,
6    output: Option<PathBuf>,
7    name: Option<String>,
8    force: bool,
9    verbose: bool,
10) -> Result<()> {
11    if verbose {
12        println!("🔧 Generating code:");
13        println!("  Template: {}", template);
14        println!(
15            "  Output: {}", output.as_ref().map(| p | p.display().to_string())
16            .unwrap_or_else(|| "current directory".to_string())
17        );
18        println!("  Name: {}", name.as_deref().unwrap_or("generated"));
19    }
20    let project_dir = find_project_root()?;
21    let output_path = output.unwrap_or_else(|| project_dir.join("src"));
22    fs::create_dir_all(&output_path).context("Failed to create output directory")?;
23    match template.as_str() {
24        "agent" => generate_agent_template(&output_path, name, force, verbose)?,
25        "workflow" => generate_workflow_template(&output_path, name, force, verbose)?,
26        "crew" => generate_crew_template(&output_path, name, force, verbose)?,
27        "context" => generate_context_template(&output_path, name, force, verbose)?,
28        "test" => generate_test_template(&output_path, name, force, verbose)?,
29        "benchmark" => generate_benchmark_template(&output_path, name, force, verbose)?,
30        _ => {
31            return Err(
32                anyhow::anyhow!(
33                    "Unknown template '{}'. Available templates: agent, workflow, crew, context, test, benchmark",
34                    template
35                ),
36            );
37        }
38    }
39    println!("✅ Generated {} template successfully!", template);
40    Ok(())
41}
42fn generate_agent_template(
43    output_path: &PathBuf,
44    name: Option<String>,
45    force: bool,
46    verbose: bool,
47) -> Result<()> {
48    let agent_name = name.unwrap_or_else(|| "MyAgent".to_string());
49    let filename = format!("{}.hlx", agent_name.to_lowercase());
50    let file_path = output_path.join(&filename);
51    if file_path.exists() && !force {
52        return Err(
53            anyhow::anyhow!(
54                "File '{}' already exists. Use --force to overwrite.", file_path
55                .display()
56            ),
57        );
58    }
59    let template = format!(
60        r#"// {} - AI Agent Configuration
61// Generated by HELIX Compiler
62
63agent {} {{
64    name: "{}"
65    description: "AI agent for {}"
66    model: "gpt-4"
67    temperature: 0.7
68    max_tokens: 2048
69    
70    system_prompt: |
71        You are {}, a specialized AI agent.
72        Your role is to assist with {}.
73        
74        Guidelines:
75        - Be helpful and accurate
76        - Provide clear explanations
77        - Ask clarifying questions when needed
78    
79    capabilities: [
80        "reasoning"
81        "analysis"
82        "communication"
83    ]
84    
85    tools: [
86        // Add tool configurations here
87    ]
88    
89    constraints: [
90        "Always be truthful"
91        "Respect user privacy"
92        "Provide helpful responses"
93    ]
94    
95    examples: [
96        {{
97            input: "Example input"
98            output: "Expected output"
99        }}
100    ]
101}}
102"#,
103        agent_name, agent_name, agent_name, agent_name.to_lowercase(), agent_name,
104        agent_name.to_lowercase()
105    );
106    fs::write(&file_path, template).context("Failed to write agent template")?;
107    if verbose {
108        println!("  Created: {}", file_path.display());
109    }
110    Ok(())
111}
112fn generate_workflow_template(
113    output_path: &PathBuf,
114    name: Option<String>,
115    force: bool,
116    verbose: bool,
117) -> Result<()> {
118    let workflow_name = name.unwrap_or_else(|| "MyWorkflow".to_string());
119    let filename = format!("{}.hlx", workflow_name.to_lowercase());
120    let file_path = output_path.join(&filename);
121    if file_path.exists() && !force {
122        return Err(
123            anyhow::anyhow!(
124                "File '{}' already exists. Use --force to overwrite.", file_path
125                .display()
126            ),
127        );
128    }
129    let template = format!(
130        r#"// {} - Workflow Configuration
131// Generated by HELIX Compiler
132
133workflow {} {{
134    name: "{}"
135    description: "Workflow for {}"
136    
137    triggers: [
138        {{
139            type: "manual"
140            description: "Manual execution"
141        }}
142    ]
143    
144    steps: [
145        {{
146            name: "step1"
147            agent: "MyAgent"
148            input: {{
149                prompt: "Process the input data"
150            }}
151            output: "processed_data"
152        }}
153        {{
154            name: "step2"
155            agent: "MyAgent"
156            input: {{
157                data: "{{processed_data}}"
158                prompt: "Analyze the processed data"
159            }}
160            output: "analysis_result"
161        }}
162    ]
163    
164    error_handling: {{
165        retry_count: 3
166        retry_delay: 1000
167        fallback_action: "notify_admin"
168    }}
169    
170    monitoring: {{
171        enabled: true
172        metrics: ["execution_time", "success_rate", "error_count"]
173    }}
174}}
175"#,
176        workflow_name, workflow_name, workflow_name, workflow_name.to_lowercase()
177    );
178    fs::write(&file_path, template).context("Failed to write workflow template")?;
179    if verbose {
180        println!("  Created: {}", file_path.display());
181    }
182    Ok(())
183}
184fn generate_crew_template(
185    output_path: &PathBuf,
186    name: Option<String>,
187    force: bool,
188    verbose: bool,
189) -> Result<()> {
190    let crew_name = name.unwrap_or_else(|| "MyCrew".to_string());
191    let filename = format!("{}.hlx", crew_name.to_lowercase());
192    let file_path = output_path.join(&filename);
193    if file_path.exists() && !force {
194        return Err(
195            anyhow::anyhow!(
196                "File '{}' already exists. Use --force to overwrite.", file_path
197                .display()
198            ),
199        );
200    }
201    let template = format!(
202        r#"// {} - Crew Configuration
203// Generated by HELIX Compiler
204
205crew {} {{
206    name: "{}"
207    description: "Crew for {}"
208    
209    agents: [
210        {{
211            name: "Agent1"
212            role: "Primary Agent"
213            specialization: "main_task"
214        }}
215        {{
216            name: "Agent2"
217            role: "Support Agent"
218            specialization: "support_task"
219        }}
220    ]
221    
222    collaboration: {{
223        mode: "sequential"
224        communication: "structured"
225        decision_making: "consensus"
226    }}
227    
228    workflow: {{
229        name: "MyWorkflow"
230        steps: [
231            "Agent1 processes input"
232            "Agent2 reviews and validates"
233            "Both agents collaborate on final output"
234        ]
235    }}
236    
237    performance: {{
238        target_accuracy: 0.95
239        max_execution_time: 30000
240        quality_threshold: 0.8
241    }}
242}}
243"#,
244        crew_name, crew_name, crew_name, crew_name.to_lowercase()
245    );
246    fs::write(&file_path, template).context("Failed to write crew template")?;
247    if verbose {
248        println!("  Created: {}", file_path.display());
249    }
250    Ok(())
251}
252fn generate_context_template(
253    output_path: &PathBuf,
254    name: Option<String>,
255    force: bool,
256    verbose: bool,
257) -> Result<()> {
258    let context_name = name.unwrap_or_else(|| "MyContext".to_string());
259    let filename = format!("{}.hlx", context_name.to_lowercase());
260    let file_path = output_path.join(&filename);
261    if file_path.exists() && !force {
262        return Err(
263            anyhow::anyhow!(
264                "File '{}' already exists. Use --force to overwrite.", file_path
265                .display()
266            ),
267        );
268    }
269    let template = format!(
270        r#"// {} - Context Configuration
271// Generated by HELIX Compiler
272
273context {} {{
274    name: "{}"
275    description: "Context for {}"
276    
277    variables: {{
278        api_key: "{{env.API_KEY}}"
279        base_url: "https:
280        timeout: 30000
281        retry_count: 3
282    }}
283    
284    resources: [
285        {{
286            name: "database"
287            type: "postgresql"
288            connection_string: "{{env.DATABASE_URL}}"
289        }}
290        {{
291            name: "cache"
292            type: "redis"
293            connection_string: "{{env.REDIS_URL}}"
294        }}
295    ]
296    
297    environment: {{
298        development: {{
299            debug: true
300            log_level: "debug"
301        }}
302        production: {{
303            debug: false
304            log_level: "info"
305        }}
306    }}
307    
308    security: {{
309        encryption: true
310        authentication: "bearer_token"
311        rate_limiting: {{
312            requests_per_minute: 100
313            burst_limit: 200
314        }}
315    }}
316}}
317"#,
318        context_name, context_name, context_name, context_name.to_lowercase()
319    );
320    fs::write(&file_path, template).context("Failed to write context template")?;
321    if verbose {
322        println!("  Created: {}", file_path.display());
323    }
324    Ok(())
325}
326fn generate_test_template(
327    output_path: &PathBuf,
328    name: Option<String>,
329    force: bool,
330    verbose: bool,
331) -> Result<()> {
332    let test_name = name.unwrap_or_else(|| "MyTest".to_string());
333    let filename = format!("test_{}.hlx", test_name.to_lowercase());
334    let file_path = output_path.join(&filename);
335    if file_path.exists() && !force {
336        return Err(
337            anyhow::anyhow!(
338                "File '{}' already exists. Use --force to overwrite.", file_path
339                .display()
340            ),
341        );
342    }
343    let template = format!(
344        r#"
345
346test {} {{
347    name: "{}"
348    description: "Test for {}"
349    
350    setup: {{
351        
352        mock_data: true
353        test_environment: "development"
354    }}
355    
356    test_cases: [
357        {{
358            name: "basic_functionality"
359            input: {{
360                message: "Hello, world!"
361            }}
362            expected_output: {{
363                response: "Hello, world!"
364                status: "success"
365            }}
366        }}
367        {{
368            name: "error_handling"
369            input: {{
370                message: ""
371            }}
372            expected_output: {{
373                error: "Invalid input"
374                status: "error"
375            }}
376        }}
377    ]
378    
379    assertions: [
380        "response.status == 'success'"
381        "response.time < 1000"
382        "response.accuracy > 0.9"
383    ]
384    
385    cleanup: {{
386        
387        remove_temp_files: true
388        reset_state: true
389    }}
390}}
391"#,
392        test_name, test_name, test_name
393    );
394    fs::write(&file_path, template).context("Failed to write test template")?;
395    if verbose {
396        println!("  Created: {}", file_path.display());
397    }
398    Ok(())
399}
400fn generate_benchmark_template(
401    output_path: &PathBuf,
402    name: Option<String>,
403    force: bool,
404    verbose: bool,
405) -> Result<()> {
406    let benchmark_name = name.unwrap_or_else(|| "MyBenchmark".to_string());
407    let filename = format!("bench_{}.hlx", benchmark_name.to_lowercase());
408    let file_path = output_path.join(&filename);
409    if file_path.exists() && !force {
410        return Err(
411            anyhow::anyhow!(
412                "File '{}' already exists. Use --force to overwrite.", file_path
413                .display()
414            ),
415        );
416    }
417    let template = format!(
418        r#"
419
420benchmark {} {{
421    name: "{}"
422    description: "Benchmark for {}"
423    
424    configuration: {{
425        iterations: 1000
426        warmup_iterations: 100
427        timeout: 30000
428        parallel: false
429    }}
430    
431    test_data: [
432        {{
433            name: "small_input"
434            size: "1KB"
435            data: "Small test data"
436        }}
437        {{
438            name: "medium_input"
439            size: "10KB"
440            data: "Medium test data with more content"
441        }}
442        {{
443            name: "large_input"
444            size: "100KB"
445            data: "Large test data with extensive content"
446        }}
447    ]
448    
449    metrics: [
450        "execution_time"
451        "memory_usage"
452        "cpu_usage"
453        "throughput"
454    ]
455    
456    thresholds: {{
457        max_execution_time: 1000
458        max_memory_usage: 50MB
459        min_throughput: 100
460    }}
461    
462    reporting: {{
463        format: "json"
464        include_details: true
465        save_results: true
466    }}
467}}
468"#,
469        benchmark_name, benchmark_name, benchmark_name
470    );
471    fs::write(&file_path, template).context("Failed to write benchmark template")?;
472    if verbose {
473        println!("  Created: {}", file_path.display());
474    }
475    Ok(())
476}
477fn find_project_root() -> Result<PathBuf> {
478    let mut current_dir = std::env::current_dir()
479        .context("Failed to get current directory")?;
480    loop {
481        let manifest_path = current_dir.join("project.hlx");
482        if manifest_path.exists() {
483            return Ok(current_dir);
484        }
485        if let Some(parent) = current_dir.parent() {
486            current_dir = parent.to_path_buf();
487        } else {
488            break;
489        }
490    }
491    Err(anyhow::anyhow!("No HELIX project found. Run 'helix init' first."))
492}