07_python_project_generator/
07_python_project_generator.rs1use ceylon_next::agent::Agent;
19use ceylon_next::goal::{Goal, GoalStatus};
20use ceylon_next::tasks::{OutputData, TaskRequest};
21use std::collections::HashMap;
22use std::fs::{self, File};
23use std::io::{self, Write};
24use std::path::Path;
25
26fn extract_output_text(output: &OutputData) -> String {
31 match output {
32 OutputData::Text(text) => text.clone(),
33 OutputData::File(bytes) => String::from_utf8_lossy(bytes).to_string(),
34 _ => "No text output available".to_string(),
35 }
36}
37
38fn parse_output_by_file(output: &str) -> HashMap<String, String> {
43 let mut files: HashMap<String, String> = HashMap::new();
44 let mut current_file = String::new();
45 let mut current_content = String::new();
46
47 for line in output.lines() {
48 if line.starts_with("=== FILE:") {
49 if !current_file.is_empty() && !current_content.is_empty() {
51 files.insert(current_file.clone(), current_content.trim().to_string());
52 }
53
54 if let Some(filename) = line
56 .strip_prefix("=== FILE:")
57 .and_then(|s| s.strip_suffix(" ==="))
58 {
59 current_file = filename.trim().to_string();
60 current_content.clear();
61 }
62 } else if !current_file.is_empty() {
63 current_content.push_str(line);
64 current_content.push('\n');
65 }
66 }
67
68 if !current_file.is_empty() && !current_content.is_empty() {
70 files.insert(current_file, current_content.trim().to_string());
71 }
72
73 files
74}
75
76fn write_files_to_disk(files: &HashMap<String, String>, base_dir_name: &str) -> io::Result<()> {
81 let mut base_path = std::env::current_dir()?;
83 base_path.push(base_dir_name);
84
85 fs::create_dir_all(&base_path)?;
87
88 for (filename, content) in files {
89 let file_path = base_path.join(filename);
91
92 if let Some(parent) = file_path.parent() {
93 fs::create_dir_all(parent)?;
94 }
95
96 let mut f = File::create(&file_path)?;
97 f.write_all(content.as_bytes())?;
98
99 println!("ā Wrote: {}", file_path.display());
100 }
101
102 Ok(())
103}
104
105async fn example_1_basic_cli_app() {
110 println!("=== Example 1: Generate a Basic Python CLI Application ===\n");
111
112 let mut agent = Agent::new("PythonCliGenerator", "ollama::gemma3:latest");
113
114 let mut goal = Goal::new(
116 "Generate a Python command-line application with core structure".to_string()
117 );
118
119 goal.add_criterion("requirements.txt with dependencies listed".to_string());
121 goal.add_criterion("setup.py or pyproject.toml for packaging".to_string());
122 goal.add_criterion("Main CLI entry point with argument parsing".to_string());
123 goal.add_criterion("Command structure with subcommands".to_string());
124 goal.add_criterion("Basic error handling and logging".to_string());
125 goal.add_criterion("README.md with usage instructions".to_string());
126 goal.add_criterion(".gitignore for Python projects".to_string());
127
128 goal.add_sub_goal("Analyze Python CLI best practices".to_string(), 0);
130 goal.add_sub_goal("Generate project structure and directories".to_string(), 1);
131 goal.add_sub_goal("Create requirements.txt with dependencies (Click, Typer, etc)".to_string(), 2);
132 goal.add_sub_goal("Generate pyproject.toml or setup.py".to_string(), 3);
133 goal.add_sub_goal("Create main CLI module with argument parser".to_string(), 4);
134 goal.add_sub_goal("Generate subcommands and command handlers".to_string(), 5);
135 goal.add_sub_goal("Create utility modules and helpers".to_string(), 6);
136 goal.add_sub_goal("Add logging and error handling".to_string(), 7);
137 goal.add_sub_goal("Generate README with installation and usage".to_string(), 8);
138
139 goal.status = GoalStatus::InProgress;
140 agent.set_goal(goal.clone());
141
142 let task = TaskRequest::new(
144 "Generate a professional Python command-line application with the following structure:\n\
145 1. Modern argument parsing using Click or Typer\n\
146 2. Multiple subcommands (e.g., init, run, config, help)\n\
147 3. Configuration file support (YAML or JSON)\n\
148 4. Logging with different verbosity levels\n\
149 5. Error handling and graceful failure messages\n\
150 6. Proper project structure with src/ and tests/ directories\n\
151 7. pyproject.toml or setup.py for packaging\n\
152 8. requirements.txt with dev dependencies\n\
153 9. .gitignore for Python\n\
154 10. Comprehensive README with examples\n\
155 The app should be production-ready and follow Python best practices (PEP 8)."
156 );
157
158 println!("š Task: Generate a Python CLI Application\n");
159 println!("šÆ Success Criteria:");
160 for criterion in &goal.success_criteria {
161 println!(" ⢠{}", criterion.description);
162 }
163
164 println!("\nā³ Agent is generating the Python CLI app...\n");
165 let response = agent.run(task).await;
166
167 let output = extract_output_text(&response.result());
169 println!("š Generated Output:\n");
170 println!("{}\n", output);
171
172 println!("š Goal Progress: {}%", goal.get_progress());
174 println!("Status: {:?}", goal.status);
175
176 println!("\nā
Example 1 completed!\n");
177}
178
179async fn example_2_fastapi_web_app() {
184 println!("\n=== Example 2: Generate Python FastAPI Web Application ===\n");
185
186 let mut agent = Agent::new("FastApiGenerator", "ollama::gemma3:latest");
187
188 let mut goal = Goal::new(
189 "Generate a complete FastAPI web application with database integration".to_string()
190 );
191
192 goal.add_criterion("FastAPI application structure with routers".to_string());
194 goal.add_criterion("Database models using SQLAlchemy".to_string());
195 goal.add_criterion("RESTful API endpoints with CRUD operations".to_string());
196 goal.add_criterion("Request/response schemas using Pydantic".to_string());
197 goal.add_criterion("Authentication and authorization middleware".to_string());
198 goal.add_criterion("Database migrations with Alembic".to_string());
199 goal.add_criterion("Configuration management with environment variables".to_string());
200 goal.add_criterion("Unit and integration test examples".to_string());
201 goal.add_criterion("Docker setup for containerization".to_string());
202
203 goal.add_sub_goal("Design REST API endpoints structure".to_string(), 0);
205 goal.add_sub_goal("Create Pydantic models for request/response validation".to_string(), 1);
206 goal.add_sub_goal("Set up SQLAlchemy ORM with database models".to_string(), 2);
207 goal.add_sub_goal("Implement CRUD routers for resources".to_string(), 3);
208 goal.add_sub_goal("Add authentication and JWT tokens".to_string(), 4);
209 goal.add_sub_goal("Create Alembic migrations setup".to_string(), 5);
210 goal.add_sub_goal("Set up configuration with environment variables".to_string(), 6);
211 goal.add_sub_goal("Create test fixtures and example tests".to_string(), 7);
212 goal.add_sub_goal("Generate Docker and docker-compose files".to_string(), 8);
213 goal.add_sub_goal("Create comprehensive API documentation".to_string(), 9);
214
215 goal.status = GoalStatus::InProgress;
216 agent.set_goal(goal.clone());
217
218 let task = TaskRequest::new(
219 "Generate a production-ready FastAPI web application with:\n\
220 1. Modular project structure with routers for different resources\n\
221 2. Pydantic models for request/response validation\n\
222 3. SQLAlchemy ORM setup with database models\n\
223 4. CRUD operations for users, products, and orders\n\
224 5. JWT authentication and authorization middleware\n\
225 6. Role-based access control (RBAC)\n\
226 7. Alembic database migrations\n\
227 8. Environment configuration (.env support)\n\
228 9. Error handling with proper HTTP status codes\n\
229 10. Logging configuration\n\
230 11. Unit tests with pytest\n\
231 12. Integration tests with test database\n\
232 13. Docker and docker-compose for local development\n\
233 14. requirements.txt with all dependencies\n\
234 15. Comprehensive API documentation\n\
235 Use async/await patterns, follow REST conventions, and include examples."
236 );
237
238 println!("š Task: Generate FastAPI Web Application\n");
239 println!("šÆ FastAPI Features:");
240 for criterion in &goal.success_criteria {
241 println!(" ā {}", criterion.description);
242 }
243
244 println!("\nā³ Agent is generating FastAPI app...\n");
245 let response = agent.run(task).await;
246
247 let output = extract_output_text(&response.result());
248 println!("š Generated Output:\n");
249 println!("{}\n", output);
250
251 println!("š Goal Progress: {}%", goal.get_progress());
252 println!("\nā
Example 2 completed!\n");
253}
254
255async fn example_3_data_science_project() {
260 println!("\n=== Example 3: Generate Python Data Science Project ===\n");
261
262 let mut agent = Agent::new("DataScienceGenerator", "ollama::gemma3:latest");
263
264 let mut goal = Goal::new(
265 "Generate a data science project with ML pipeline and analysis".to_string()
266 );
267
268 goal.add_criterion("Project structure following cookiecutter-data-science".to_string());
269 goal.add_criterion("Data loading and preprocessing modules".to_string());
270 goal.add_criterion("Exploratory data analysis (EDA) notebooks".to_string());
271 goal.add_criterion("Feature engineering pipeline".to_string());
272 goal.add_criterion("Model training and evaluation".to_string());
273 goal.add_criterion("Hyperparameter tuning setup".to_string());
274 goal.add_criterion("Model persistence and versioning".to_string());
275 goal.add_criterion("Visualization utilities".to_string());
276 goal.add_criterion("Unit tests for data pipeline".to_string());
277
278 goal.add_sub_goal("Create cookiecutter-style directory structure".to_string(), 0);
279 goal.add_sub_goal("Set up Jupyter notebook for EDA".to_string(), 1);
280 goal.add_sub_goal("Create data loading and preprocessing modules".to_string(), 2);
281 goal.add_sub_goal("Implement feature engineering pipeline".to_string(), 3);
282 goal.add_sub_goal("Set up scikit-learn model training".to_string(), 4);
283 goal.add_sub_goal("Create model evaluation and metrics".to_string(), 5);
284 goal.add_sub_goal("Implement hyperparameter tuning with GridSearchCV".to_string(), 6);
285 goal.add_sub_goal("Add model persistence with joblib/pickle".to_string(), 7);
286 goal.add_sub_goal("Create visualization utilities with matplotlib/seaborn".to_string(), 8);
287 goal.add_sub_goal("Write tests for data pipeline".to_string(), 9);
288
289 goal.status = GoalStatus::InProgress;
290 agent.set_goal(goal.clone());
291
292 let task = TaskRequest::new(
293 "Generate a comprehensive Python data science project with:\n\
294 1. Proper project structure for data science work\n\
295 2. Data loading module supporting CSV, JSON, Parquet\n\
296 3. Data preprocessing and validation pipeline\n\
297 4. Exploratory Data Analysis (EDA) notebook template\n\
298 5. Feature engineering module\n\
299 6. Model training with scikit-learn or XGBoost\n\
300 7. Cross-validation and evaluation metrics\n\
301 8. Hyperparameter tuning with GridSearchCV/RandomSearch\n\
302 9. Model persistence and loading utilities\n\
303 10. Visualization utilities (matplotlib, seaborn, plotly)\n\
304 11. Unit tests for data loading and preprocessing\n\
305 12. Configuration management for experiments\n\
306 13. Logging for training pipeline\n\
307 14. Requirements.txt with ML libraries (pandas, numpy, scikit-learn)\n\
308 15. Makefile for common tasks\n\
309 16. README with dataset description and results\n\
310 Include example workflows and best practices for reproducibility."
311 );
312
313 println!("š Task: Generate Data Science Project\n");
314 println!("šÆ Data Science Features:");
315 for criterion in &goal.success_criteria {
316 println!(" ā {}", criterion.description);
317 }
318
319 println!("\nā³ Agent is generating data science project...\n");
320 let response = agent.run(task).await;
321
322 let output = extract_output_text(&response.result());
323 println!("š Generated Output:\n");
324 println!("{}\n", output);
325
326 println!("š Goal Progress: {}%", goal.get_progress());
327 println!("\nā
Example 3 completed!\n");
328}
329
330async fn example_4_python_library() {
335 println!("\n=== Example 4: Generate Python Library/Package ===\n");
336
337 let mut agent = Agent::new("PythonLibraryGenerator", "ollama::gemma3:latest");
338
339 let mut goal = Goal::new(
340 "Generate a well-structured Python package ready for distribution".to_string()
341 );
342
343 goal.add_criterion("Proper package structure with namespace".to_string());
344 goal.add_criterion("setup.py and pyproject.toml for distribution".to_string());
345 goal.add_criterion("Comprehensive docstrings and type hints".to_string());
346 goal.add_criterion("Unit tests with pytest".to_string());
347 goal.add_criterion("Documentation with Sphinx".to_string());
348 goal.add_criterion("CI/CD configuration (GitHub Actions)".to_string());
349 goal.add_criterion("Version management strategy".to_string());
350 goal.add_criterion("Contributing guidelines".to_string());
351
352 goal.add_sub_goal("Create package structure with __init__.py files".to_string(), 0);
353 goal.add_sub_goal("Write setup.py and pyproject.toml".to_string(), 1);
354 goal.add_sub_goal("Create core modules with type hints".to_string(), 2);
355 goal.add_sub_goal("Add comprehensive docstrings".to_string(), 3);
356 goal.add_sub_goal("Create test structure with pytest".to_string(), 4);
357 goal.add_sub_goal("Set up documentation with Sphinx".to_string(), 5);
358 goal.add_sub_goal("Create GitHub Actions workflows".to_string(), 6);
359 goal.add_sub_goal("Add CONTRIBUTING.md and CODE_OF_CONDUCT.md".to_string(), 7);
360 goal.add_sub_goal("Create MANIFEST.in and manifest files".to_string(), 8);
361
362 goal.status = GoalStatus::InProgress;
363 agent.set_goal(goal.clone());
364
365 let task = TaskRequest::new(
366 "Generate a professional Python library/package with:\n\
367 1. Standard package structure (src layout)\n\
368 2. __init__.py with version and exports\n\
369 3. Core modules with complete implementations\n\
370 4. Type hints throughout (PEP 484)\n\
371 5. Comprehensive docstrings (Google style)\n\
372 6. setup.py with metadata\n\
373 7. pyproject.toml with build system\n\
374 8. MANIFEST.in for package data\n\
375 9. Pytest test structure with fixtures\n\
376 10. pytest.ini configuration\n\
377 11. Sphinx documentation setup\n\
378 12. GitHub Actions workflow for CI/CD\n\
379 13. Pre-commit hooks configuration\n\
380 14. LICENSE (MIT or Apache 2.0)\n\
381 15. .gitignore for Python\n\
382 16. README.md with installation and usage\n\
383 17. CONTRIBUTING.md for contributors\n\
384 18. CODE_OF_CONDUCT.md\n\
385 19. Changelog/HISTORY.md template\n\
386 20. Version management with __version__\n\
387 Include examples for public API and best practices for library development."
388 );
389
390 println!("š Task: Generate Python Library Package\n");
391 println!("šÆ Library Features:");
392 for criterion in &goal.success_criteria {
393 println!(" ā {}", criterion.description);
394 }
395
396 println!("\nā³ Agent is generating Python library...\n");
397 let response = agent.run(task).await;
398
399 let output = extract_output_text(&response.result());
400 println!("š Generated Output:\n");
401 println!("{}\n", output);
402
403 println!("š Goal Progress: {}%", goal.get_progress());
404 println!("\nā
Example 4 completed!\n");
405}
406
407async fn example_5_django_web_app() {
412 println!("\n=== Example 5: Generate Django Web Application ===\n");
413
414 let mut agent = Agent::new("DjangoGenerator", "ollama::gemma3:latest");
415
416 let mut goal = Goal::new(
417 "Generate a complete Django web application with admin and authentication".to_string()
418 );
419
420 goal.add_criterion("Django project structure with multiple apps".to_string());
421 goal.add_criterion("Custom user model implementation".to_string());
422 goal.add_criterion("Database models for core features".to_string());
423 goal.add_criterion("Admin interface customization".to_string());
424 goal.add_criterion("Views and URL routing".to_string());
425 goal.add_criterion("Templates with Bootstrap styling".to_string());
426 goal.add_criterion("Authentication and permissions".to_string());
427 goal.add_criterion("Database migrations".to_string());
428 goal.add_criterion("Django REST Framework API".to_string());
429
430 goal.add_sub_goal("Create Django project and app structure".to_string(), 0);
431 goal.add_sub_goal("Design and implement custom user model".to_string(), 1);
432 goal.add_sub_goal("Create models for core features".to_string(), 2);
433 goal.add_sub_goal("Configure admin interface".to_string(), 3);
434 goal.add_sub_goal("Create views and templates".to_string(), 4);
435 goal.add_sub_goal("Set up URL routing".to_string(), 5);
436 goal.add_sub_goal("Implement authentication views".to_string(), 6);
437 goal.add_sub_goal("Create Django REST Framework serializers".to_string(), 7);
438 goal.add_sub_goal("Set up static files and media handling".to_string(), 8);
439
440 goal.status = GoalStatus::InProgress;
441 agent.set_goal(goal.clone());
442
443 let task = TaskRequest::new(
444 "Generate a full-featured Django web application with:\n\
445 1. Django project structure with multiple apps\n\
446 2. Custom user model extending AbstractBaseUser\n\
447 3. Models for main features (e.g., Blog posts, Comments, Categories)\n\
448 4. Django ORM relationships (ForeignKey, ManyToMany)\n\
449 5. Admin interface with custom actions\n\
450 6. Class-based views (ListView, DetailView, CreateView)\n\
451 7. Django templates with template inheritance\n\
452 8. Bootstrap styling integration\n\
453 9. Authentication and login required decorators\n\
454 10. Permission-based access control\n\
455 11. Database migrations\n\
456 12. Forms with validation\n\
457 13. Django REST Framework setup\n\
458 14. API serializers and viewsets\n\
459 15. Pagination and filtering\n\
460 16. Settings for dev and production\n\
461 17. Environment variable configuration\n\
462 18. Logging configuration\n\
463 19. Tests with Django TestCase\n\
464 20. Static files and media management\n\
465 21. Docker setup\n\
466 22. Requirements.txt\n\
467 Include examples and docstrings following Django conventions."
468 );
469
470 println!("š Task: Generate Django Web Application\n");
471 println!("šÆ Django Features:");
472 for criterion in &goal.success_criteria {
473 println!(" ā {}", criterion.description);
474 }
475
476 println!("\nā³ Agent is generating Django app...\n");
477 let response = agent.run(task).await;
478
479 let output = extract_output_text(&response.result());
480 println!("š Generated Output:\n");
481 println!("{}\n", output);
482
483 println!("š Goal Progress: {}%", goal.get_progress());
484 println!("\nā
Example 5 completed!\n");
485}
486
487async fn example_6_output_extraction() {
492 println!("\n=== Example 6: Output Extraction and File Organization ===\n");
493
494 let mut agent = Agent::new("PythonFileProcessor", "ollama::gemma3:latest");
495
496 let task = TaskRequest::new(
498 "Generate ONLY the following Python project files in proper format:\n\
499 1. A requirements.txt with common Python dependencies\n\
500 2. A setup.py for package setup\n\
501 3. A .gitignore for Python projects\n\
502 4. A main.py entry point\n\
503 5. A config.py module\n\
504 Format each file with proper headers like:\n\
505 === FILE: requirements.txt ===\n\
506 [file content]\n\
507 === FILE: setup.py ===\n\
508 [file content]\n\
509 Make sure each file is complete and ready to use."
510 );
511
512 println!("š Task: Generate Core Python Project Files\n");
513 println!("ā³ Processing...\n");
514
515 let response = agent.run(task).await;
516 let output = extract_output_text(&response.result());
517
518 let files: HashMap<String, String> = parse_output_by_file(&output);
520
521 println!("š¦ Generated Python Files:\n");
522 let mut total_lines = 0;
523 let mut total_bytes = 0;
524
525 for (filename, content) in &files {
526 let lines = content.lines().count();
527 let bytes = content.len();
528 total_lines += lines;
529 total_bytes += bytes;
530
531 println!("š File: {}", filename);
532 println!(" Lines: {}", lines);
533 println!(" Size: {} bytes", bytes);
534
535 if lines <= 10 {
536 println!(" Preview:");
537 for line in content.lines() {
538 println!(" {}", line);
539 }
540 }
541 println!();
542 }
543
544 println!("š Project Statistics:");
545 println!(" Total Files: {}", files.len());
546 println!(" Total Lines: {}", total_lines);
547 println!(" Total Size: {} bytes", total_bytes);
548
549 let output_folder = "generated_python_project";
551 match write_files_to_disk(&files, output_folder) {
552 Ok(_) => {
553 let mut full_path = std::env::current_dir().unwrap();
554 full_path.push(output_folder);
555 println!("\nā
All files written to: {}", full_path.display());
556 }
557 Err(e) => {
558 eprintln!("\nā ļø Failed to write files to disk: {}", e);
559 }
560 }
561
562 println!("\nā
Example 6 completed!\n");
563}
564
565#[tokio::main]
570async fn main() {
571 println!("š Ceylon Agent - Python Project Generator Examples\n");
572 println!("This example demonstrates how to use Ceylon agents to:");
573 println!(" ⢠Generate Python projects of various types");
574 println!(" ⢠Create project structures and configuration files");
575 println!(" ⢠Generate boilerplate code and dependencies");
576 println!(" ⢠Extract and organize generated files\n");
577 println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
578
579 example_1_basic_cli_app().await;
581 example_2_fastapi_web_app().await;
582 example_3_data_science_project().await;
583 example_4_python_library().await;
584 example_5_django_web_app().await;
585 example_6_output_extraction().await;
586
587 println!("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
588 println!("\nā
All Python project generator examples completed successfully!\n");
589
590 println!("š Key Takeaways:");
591 println!(" 1. Goals structure project generation into clear steps");
592 println!(" 2. Success criteria define required files and features");
593 println!(" 3. Different Python project types have distinct requirements");
594 println!(" 4. Extract output and parse by file sections");
595 println!(" 5. Combine with tools for actual file system operations\n");
596
597 println!("š Python Project Types Demonstrated:");
598 println!(" ⢠CLI Applications (Click, Typer, argparse)");
599 println!(" ⢠Web APIs (FastAPI with async patterns)");
600 println!(" ⢠Data Science (ML pipelines with scikit-learn)");
601 println!(" ⢠Libraries/Packages (for PyPI distribution)");
602 println!(" ⢠Web Frameworks (Django with full-stack features)\n");
603
604 println!("āļø Next steps:");
605 println!(" ⢠Add tools to write generated files to disk");
606 println!(" ⢠Create tools for running pip install, pytest, and other commands");
607 println!(" ⢠Integrate with virtual environment creation");
608 println!(" ⢠Add validation tools to verify Python syntax");
609 println!(" ⢠Store generated code in memory for multi-step workflows");
610 println!(" ⢠Add tools for running linting (flake8, black) and type checking (mypy)\n");
611
612 println!("š” Example: Connecting to Tools");
613 println!("```rust");
614 println!("// Create file writing tool");
615 println!("let file_tool = FileWriterTool::new(\"/path/to/project\");");
616 println!("agent.add_tool(Arc::new(file_tool));");
617 println!("");
618 println!("// Create virtual environment tool");
619 println!("let venv_tool = VenvTool::new();");
620 println!("agent.add_tool(Arc::new(venv_tool));");
621 println!("");
622 println!("// Agent can now create complete projects");
623 println!("let response = agent.run(task).await;");
624 println!("```\n");
625}
626
627