opencrates 3.0.1

Enterprise-grade AI-powered Rust development companion with comprehensive automation, monitoring, and deployment capabilities
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
//! Stage orchestrator for crate generation pipeline
//!
//! This module provides comprehensive orchestration of the crate generation process
//! through various specialized stages, each handling specific aspects of crate creation.

use anyhow::Result;
use tracing::{debug, info, warn};

use crate::providers::OpenAIProvider;
use crate::utils::templates::TemplateManager;

/// Architect stage for designing crate structure and architecture
pub mod architect;
/// Conceptualizer stage for analyzing and refining crate concepts
pub mod conceptualizer;
/// Pipeline infrastructure for coordinating stage execution
pub mod pipeline;

pub use architect::{Architect, ArchitectStage};
pub use conceptualizer::{ConceptualizationStage, Conceptualizer};
pub use pipeline::{run_pipeline, CrateContext, GenerationPipeline};

/// Main orchestrator that coordinates all stages of crate generation
/// Provides a unified interface for executing the complete pipeline
#[derive(Clone)]
pub struct StageOrchestrator {
    openai_provider: OpenAIProvider,
    conceptualizer: Conceptualizer,
    architect: Architect,
}

impl StageOrchestrator {
    /// Creates a new stage orchestrator with the provided `OpenAI` provider
    ///
    /// # Arguments
    /// * `openai_provider` - The `OpenAI` provider for AI-powered generation
    ///
    /// # Returns
    /// A new `StageOrchestrator` instance
    #[must_use]
    pub fn new(openai_provider: OpenAIProvider) -> Self {
        Self {
            conceptualizer: Conceptualizer::new(openai_provider.clone()),
            architect: Architect::new(openai_provider.clone()),
            openai_provider,
        }
    }

    /// Gets a reference to the `OpenAI` provider
    ///
    /// # Returns
    /// Reference to the underlying `OpenAI` provider
    #[must_use]
    pub fn openai(&self) -> &OpenAIProvider {
        &self.openai_provider
    }

    /// Executes the conceptualization stage
    ///
    /// Analyzes the initial idea and creates a detailed concept with enhanced context
    ///
    /// # Arguments
    /// * `context` - The current crate context
    /// * `enhanced_context` - Additional context information for conceptualization
    ///
    /// # Returns
    /// Updated context with conceptualization results
    ///
    /// # Errors
    /// Returns an error if conceptualization fails
    pub async fn conceptualize(
        &self,
        mut context: CrateContext,
        enhanced_context: &str,
    ) -> Result<CrateContext> {
        info!("Stage 1: Conceptualizing crate");

        let start_time = std::time::Instant::now();
        context = self
            .conceptualizer
            .execute(context, enhanced_context)
            .await?;

        let duration = start_time.elapsed();
        debug!("Conceptualization completed in {:?}", duration);

        // Record stage metrics
        context.set_stage_output(
            "conceptualization_metrics",
            serde_json::json!({
                "duration_ms": duration.as_millis(),
                "enhanced_context_length": enhanced_context.len()
            }),
        );

        Ok(context)
    }

    /// Executes the architecture stage
    ///
    /// Designs the crate structure, modules, and overall architecture
    ///
    /// # Arguments
    /// * `context` - The current crate context
    ///
    /// # Returns
    /// Updated context with architectural design
    ///
    /// # Errors
    /// Returns an error if architecture design fails
    pub async fn architect(&self, mut context: CrateContext) -> Result<CrateContext> {
        info!("Stage 2: Architecting crate structure");

        let start_time = std::time::Instant::now();
        context = self.architect.execute(context).await?;

        let duration = start_time.elapsed();
        debug!("Architecture completed in {:?}", duration);

        // Record stage metrics
        context.set_stage_output(
            "architecture_metrics",
            serde_json::json!({
                "duration_ms": duration.as_millis(),
                "modules_designed": context.get_file_paths().len()
            }),
        );

        Ok(context)
    }

    /// Executes the complete pipeline with all stages
    ///
    /// Runs conceptualization, architecture, and all subsequent stages
    ///
    /// # Arguments
    /// * `context` - The initial crate context
    /// * `enhanced_context` - Additional context for conceptualization
    ///
    /// # Returns
    /// Final context with complete crate generation
    ///
    /// # Errors
    /// Returns an error if any stage fails
    pub async fn execute_full_pipeline(
        &self,
        context: CrateContext,
        enhanced_context: &str,
    ) -> Result<CrateContext> {
        info!("Executing full crate generation pipeline");

        let pipeline_start = std::time::Instant::now();

        // Stage 1: Conceptualization
        let context = self.conceptualize(context, enhanced_context).await?;

        // Stage 2: Architecture
        let context = self.architect(context).await?;

        // Stage 3: Packaging
        let context = self.package(context, None).await?;

        // Stage 4: Testing
        let context = self.test(context).await?;

        // Stage 5: Documentation
        let context = self.document(context).await?;

        // Stage 6: Deployment preparation
        let context = self.deploy(context).await?;

        // Stage 7: Final refinement
        let context = self.refine(context).await?;

        let total_duration = pipeline_start.elapsed();
        info!("Pipeline completed successfully in {:?}", total_duration);

        Ok(context)
    }

    /// Executes the packaging stage
    ///
    /// Generates all necessary files using templates and renders the final crate structure
    ///
    /// # Arguments
    /// * `context` - The current crate context
    /// * `template` - Optional template name to use for packaging
    ///
    /// # Returns
    /// Updated context with packaged files
    ///
    /// # Errors
    /// Returns an error if packaging fails
    pub async fn package(
        &self,
        mut context: CrateContext,
        template: Option<&str>,
    ) -> Result<CrateContext> {
        info!("Stage 3: Packaging crate files");

        let start_time = std::time::Instant::now();
        let template_manager = TemplateManager::new().await?;

        // Use render_crate to generate the files
        let generated_files = template_manager
            .render_crate(&context, &context.output_path)
            .await?;

        // Add generated files to context
        for (path, content) in &generated_files {
            context.add_file(path, content.clone());
        }

        let duration = start_time.elapsed();
        debug!("Packaging completed in {:?}", duration);

        // Record packaging metrics
        context.set_stage_output(
            "packaging_metrics",
            serde_json::json!({
                "duration_ms": duration.as_millis(),
                "files_generated": generated_files.len(),
                "template_used": template.unwrap_or("default")
            }),
        );

        Ok(context)
    }

    /// Executes the testing stage
    ///
    /// Generates comprehensive tests and validates the crate functionality
    ///
    /// # Arguments
    /// * `context` - The current crate context
    ///
    /// # Returns
    /// Updated context with test files and validation results
    ///
    /// # Errors
    /// Returns an error if test generation fails
    pub async fn test(&self, mut context: CrateContext) -> Result<CrateContext> {
        info!("Stage 4: Generating tests and validation");

        let start_time = std::time::Instant::now();

        // Generate unit tests
        let unit_tests = self.generate_unit_tests(&context).await?;
        context.add_file("src/tests.rs", unit_tests);

        // Generate integration tests
        let integration_tests = self.generate_integration_tests(&context).await?;
        context.add_file("tests/integration.rs", integration_tests);

        // Generate benchmarks
        let benchmarks = self.generate_benchmarks(&context).await?;
        context.add_file("benches/benchmarks.rs", benchmarks);

        let duration = start_time.elapsed();
        debug!("Testing stage completed in {:?}", duration);

        // Record testing metrics
        context.set_stage_output(
            "testing_metrics",
            serde_json::json!({
                "duration_ms": duration.as_millis(),
                "unit_tests_generated": true,
                "integration_tests_generated": true,
                "benchmarks_generated": true
            }),
        );

        Ok(context)
    }

    /// Executes the documentation stage
    ///
    /// Generates comprehensive documentation including API docs, examples, and guides
    ///
    /// # Arguments
    /// * `context` - The current crate context
    ///
    /// # Returns
    /// Updated context with documentation files
    ///
    /// # Errors
    /// Returns an error if documentation generation fails
    pub async fn document(&self, mut context: CrateContext) -> Result<CrateContext> {
        info!("Stage 5: Generating documentation");

        let start_time = std::time::Instant::now();

        // Generate API documentation
        let api_docs = self.generate_api_docs(&context).await?;
        context.add_file("docs/api.md", api_docs);

        // Generate usage examples
        let examples = self.generate_examples(&context).await?;
        context.add_file("examples/basic_usage.rs", examples);

        // Generate user guide
        let user_guide = self.generate_user_guide(&context).await?;
        context.add_file("docs/user_guide.md", user_guide);

        let duration = start_time.elapsed();
        debug!("Documentation stage completed in {:?}", duration);

        // Record documentation metrics
        context.set_stage_output(
            "documentation_metrics",
            serde_json::json!({
                "duration_ms": duration.as_millis(),
                "api_docs_generated": true,
                "examples_generated": true,
                "user_guide_generated": true
            }),
        );

        Ok(context)
    }

    /// Executes the deployment preparation stage
    ///
    /// Prepares the crate for deployment including CI/CD setup and publishing configuration
    ///
    /// # Arguments
    /// * `context` - The current crate context
    ///
    /// # Returns
    /// Updated context with deployment files
    ///
    /// # Errors
    /// Returns an error if deployment preparation fails
    pub async fn deploy(&self, mut context: CrateContext) -> Result<CrateContext> {
        info!("Stage 6: Preparing deployment configuration");

        let start_time = std::time::Instant::now();

        // Generate CI/CD configuration
        let github_actions = self.generate_github_actions(&context).await?;
        context.add_file(".github/workflows/ci.yml", github_actions);

        // Generate Docker configuration
        let dockerfile = self.generate_dockerfile(&context).await?;
        context.add_file("Dockerfile", dockerfile);

        // Generate release configuration
        let release_config = self.get_release_config()?;
        context.add_file("release.toml", release_config);

        let duration = start_time.elapsed();
        debug!("Deployment stage completed in {:?}", duration);

        // Record deployment metrics
        context.set_stage_output(
            "deployment_metrics",
            serde_json::json!({
                "duration_ms": duration.as_millis(),
                "ci_cd_generated": true,
                "docker_generated": true,
                "release_config_generated": true
            }),
        );

        Ok(context)
    }

    /// Executes the refinement stage
    ///
    /// Performs final optimizations, code formatting, and quality checks
    ///
    /// # Arguments
    /// * `context` - The current crate context
    ///
    /// # Returns
    /// Final refined context
    ///
    /// # Errors
    /// Returns an error if refinement fails
    pub async fn refine(&self, mut context: CrateContext) -> Result<CrateContext> {
        info!("Stage 7: Final refinement and optimization");

        let start_time = std::time::Instant::now();

        // Optimize generated code
        context = self.optimize_code(context).await?;

        // Format all code files
        context = self.format_code(context).await?;

        // Validate final output
        let validation_results = self.validate_final_output(&context).await?;

        let duration = start_time.elapsed();
        debug!("Refinement stage completed in {:?}", duration);

        // Record refinement metrics
        context.set_stage_output(
            "refinement_metrics",
            serde_json::json!({
                "duration_ms": duration.as_millis(),
                "code_optimized": true,
                "code_formatted": true,
                "validation_passed": validation_results.is_empty()
            }),
        );

        if !validation_results.is_empty() {
            warn!("Validation issues found: {:?}", validation_results);
        }

        Ok(context)
    }

    // Private helper methods for individual stage operations

    async fn generate_unit_tests(&self, context: &CrateContext) -> Result<String> {
        let prompt = format!(
            "Generate comprehensive unit tests for a Rust crate named '{}' with description: '{}'",
            context.crate_name, context.description
        );

        let response = self.openai_provider.chat("gpt-4", &prompt).await?;
        Ok(response)
    }

    async fn generate_integration_tests(&self, context: &CrateContext) -> Result<String> {
        let prompt = format!(
            "Generate integration tests for a Rust crate named '{}' that tests end-to-end functionality",
            context.crate_name
        );

        let response = self.openai_provider.chat("gpt-4", &prompt).await?;
        Ok(response)
    }

    async fn generate_benchmarks(&self, context: &CrateContext) -> Result<String> {
        let prompt = format!(
            "Generate performance benchmarks using criterion for a Rust crate named '{}'",
            context.crate_name
        );

        let response = self.openai_provider.chat("gpt-4", &prompt).await?;
        Ok(response)
    }

    async fn generate_api_docs(&self, context: &CrateContext) -> Result<String> {
        let prompt = format!(
            "Generate comprehensive API documentation for a Rust crate named '{}' with description: '{}'",
            context.crate_name, context.description
        );

        let response = self.openai_provider.chat("gpt-4", &prompt).await?;
        Ok(response)
    }

    async fn generate_examples(&self, context: &CrateContext) -> Result<String> {
        let prompt = format!(
            "Generate practical usage examples for a Rust crate named '{}' that demonstrate core functionality",
            context.crate_name
        );

        let response = self.openai_provider.chat("gpt-4", &prompt).await?;
        Ok(response)
    }

    async fn generate_user_guide(&self, context: &CrateContext) -> Result<String> {
        let prompt = format!(
            "Generate a comprehensive user guide for a Rust crate named '{}' including installation, configuration, and usage",
            context.crate_name
        );

        let response = self.openai_provider.chat("gpt-4", &prompt).await?;
        Ok(response)
    }

    async fn generate_github_actions(&self, _context: &CrateContext) -> Result<String> {
        let ci_config = r"name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

env:
  CARGO_TERM_COLOR: always

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Install Rust
      uses: actions-rs/toolchain@v1
      with:
        toolchain: stable
        profile: minimal
        override: true
        components: rustfmt, clippy
    
    - name: Cache dependencies
      uses: actions/cache@v3
      with:
        path: ~/.cargo
        key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
    
    - name: Check formatting
      run: cargo fmt --all -- --check
    
    - name: Run clippy
      run: cargo clippy -- -D warnings
    
    - name: Run tests
      run: cargo test --verbose
    
    - name: Run benchmarks
      run: cargo bench
      
  build:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Install Rust
      uses: actions-rs/toolchain@v1
      with:
        toolchain: stable
        profile: minimal
        override: true
    
    - name: Build
      run: cargo build --release --verbose

  publish:
    runs-on: ubuntu-latest
    needs: [test, build]
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Install Rust
      uses: actions-rs/toolchain@v1
      with:
        toolchain: stable
        profile: minimal
        override: true
    
    - name: Publish to crates.io
      env:
        CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
      run: cargo publish --dry-run
"
        .to_string();

        Ok(ci_config)
    }

    async fn generate_dockerfile(&self, context: &CrateContext) -> Result<String> {
        let dockerfile = format!(
            r#"FROM rust:1.70 as builder

WORKDIR /app
COPY . .
RUN cargo build --release

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

COPY --from=builder /app/target/release/{} /usr/local/bin/{}

EXPOSE 8080

CMD ["{}"]
"#,
            context.crate_name, context.crate_name, context.crate_name
        );

        Ok(dockerfile)
    }

    fn get_release_config(&self) -> Result<String> {
        let release_config = r#"[package]
sign-commit = false
sign-tag = false
pre-release-commit-message = "Release version {{version}}"
tag-message = "Release {{version}}"

[build]
pre-release-hook = ["cargo", "check"]
"#;
        Ok(release_config.to_string())
    }

    async fn optimize_code(&self, mut context: CrateContext) -> Result<CrateContext> {
        debug!("Optimizing generated code");

        // Perform code optimizations like removing unused imports,
        // optimizing data structures, etc.
        // This is a placeholder for actual optimization logic

        context.set_metadata("optimized".to_string(), "true".to_string());
        Ok(context)
    }

    async fn format_code(&self, mut context: CrateContext) -> Result<CrateContext> {
        debug!("Formatting generated code");

        // Apply consistent code formatting
        // This would integrate with rustfmt in a real implementation

        context.set_metadata("formatted".to_string(), "true".to_string());
        Ok(context)
    }

    async fn validate_final_output(&self, context: &CrateContext) -> Result<Vec<String>> {
        debug!("Validating final output");

        let mut issues = Vec::new();

        // Check for required files
        let required_files = ["Cargo.toml", "src/lib.rs", "README.md"];
        for file in required_files {
            if !context.generated_files.contains_key(file) {
                issues.push(format!("Missing required file: {file}"));
            }
        }

        // Check for valid Cargo.toml
        if let Some(cargo_content) = context.get_file_content("Cargo.toml") {
            if !cargo_content.contains(&context.crate_name) {
                issues.push("Cargo.toml does not contain crate name".to_string());
            }
        }

        // Additional validations can be added here

        Ok(issues)
    }
}