44import json # Move from within functions to top level
55from typing import Dict , List , Optional
66from dotenv import load_dotenv
7+ import tempfile # Import tempfile for temporary directory handling
78
89# Load environment variables from .env file
910load_dotenv ()
@@ -358,6 +359,150 @@ async def download_project(project_id: str):
358359 media_type = "application/zip"
359360 )
360361
362+ @app .post ("/generate-sync" )
363+ async def generate_project_sync (request : ProjectRequest ):
364+ """
365+ Generate a Rust project synchronously and return all files in text format.
366+ This endpoint will wait for the full generation process to complete.
367+ """
368+ try :
369+ # Create temporary directory for generation
370+ with tempfile .TemporaryDirectory () as temp_dir :
371+ # Set up status tracking
372+ status = {
373+ "status" : "generating" ,
374+ "message" : "Generating project code"
375+ }
376+
377+ # Skip vector search if environment variable is set
378+ skip_vector_search = os .getenv ("SKIP_VECTOR_SEARCH" , "" ).lower () == "true"
379+
380+ example_text = ""
381+ if not skip_vector_search :
382+ try :
383+ # Check for similar projects in vector DB
384+ query_embedding = llm_client .get_embeddings ([request .description ])[0 ]
385+ similar_projects = vector_store .search ("project_examples" , query_embedding , limit = 1 )
386+
387+ if similar_projects :
388+ example_text = f"\n Here's a similar project you can use as reference:\n { similar_projects [0 ]['example' ]} "
389+ except Exception as e :
390+ print (f"Vector search error (non-critical): { e } " )
391+
392+ requirements = request .requirements or ""
393+ if example_text :
394+ requirements = f"{ requirements } \n { example_text } " if requirements else example_text
395+
396+ # Generate prompt and get response from LLM
397+ prompt = prompt_gen .generate_prompt (request .description , requirements )
398+
399+ system_message = """You are an expert Rust developer. Create a complete, working Rust project.
400+ Always include at minimum these files: Cargo.toml, src/main.rs, and README.md.
401+ For Cargo.toml, include proper dependencies and metadata.
402+ Format your response with clear file headers like:
403+
404+ [filename: Cargo.toml]
405+ <file content>
406+
407+ [filename: src/main.rs]
408+ <file content>
409+ """
410+
411+ response = llm_client .generate_text (prompt , system_message = system_message )
412+
413+ # Parse response into files
414+ files = parser .parse_response (response )
415+
416+ # Ensure essential files exist
417+ if "Cargo.toml" not in files :
418+ project_name = request .description .lower ().replace (" " , "_" ).replace ("-" , "_" )[:20 ]
419+ files ["Cargo.toml" ] = f"""[package]
420+ name = "{ project_name } "
421+ version = "0.1.0"
422+ edition = "2021"
423+
424+ [dependencies]
425+ """
426+
427+ if "src/main.rs" not in files and "src\\ main.rs" not in files :
428+ files ["src/main.rs" ] = """fn main() {
429+ println!("Hello, world!");
430+ }
431+ """
432+
433+ # Write files
434+ parser .write_files (files , temp_dir )
435+
436+ # Compile the project
437+ success , output = compiler .build_project (temp_dir )
438+
439+ if not success :
440+ # Try to fix compilation errors
441+ error_context = compiler .extract_error_context (output )
442+
443+ # Skip vector search if environment variable is set
444+ similar_errors = []
445+ if not skip_vector_search :
446+ try :
447+ error_embedding = llm_client .get_embeddings ([error_context ["full_error" ]])[0 ]
448+ similar_errors = vector_store .search ("error_examples" , error_embedding , limit = 3 )
449+ except Exception as e :
450+ print (f"Vector search error (non-critical): { e } " )
451+
452+ # Generate fix prompt
453+ fix_examples = ""
454+ if similar_errors :
455+ fix_examples = "Here are some examples of similar errors and their fixes:\n \n "
456+ for i , err in enumerate (similar_errors ):
457+ fix_examples += f"Example { i + 1 } :\n { err ['error' ]} \n Fix: { err ['solution' ]} \n \n "
458+
459+ fix_prompt = f"""
460+ Here is a Rust project that failed to compile. Help me fix the compilation errors.
461+
462+ Project description: { request .description }
463+
464+ Compilation error:
465+ { error_context ["full_error" ]}
466+
467+ { fix_examples }
468+
469+ Please provide the fixed code for all affected files.
470+ """
471+
472+ # Get fix from LLM
473+ fix_response = llm_client .generate_text (fix_prompt )
474+
475+ # Parse and apply fixes
476+ fixed_files = parser .parse_response (fix_response )
477+ for filename , content in fixed_files .items ():
478+ files [filename ] = content # Update our files dictionary
479+ file_path = os .path .join (temp_dir , filename )
480+ os .makedirs (os .path .dirname (file_path ), exist_ok = True )
481+ with open (file_path , 'w' ) as f :
482+ f .write (content )
483+
484+ # Try compiling again
485+ success , output = compiler .build_project (temp_dir )
486+
487+ # Format as raw text with filename markers
488+ output_text = ""
489+ for filename , content in files .items ():
490+ output_text += f"[filename: { filename } ]\n { content } \n \n "
491+
492+ # Include build result as a comment
493+ build_status = "# Build succeeded" if success else f"# Build failed\n # { output } "
494+ output_text += f"{ build_status } \n "
495+
496+ # Return as plain text
497+ return PlainTextResponse (content = output_text .strip ())
498+
499+ except Exception as e :
500+ # Return error message
501+ return JSONResponse (
502+ status_code = 500 ,
503+ content = {"error" : f"Project generation failed: { str (e )} " }
504+ )
505+
361506if __name__ == "__main__" :
362507 import uvicorn
363508 uvicorn .run ("app.main:app" , host = "0.0.0.0" , port = 8000 , reload = True )
0 commit comments