diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..16ddac3 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +GEMINI_API_KEY="YOUR_API_KEY_HERE" diff --git a/.github/bug_report.md b/.github/bug_report.md new file mode 100644 index 0000000..e5875b1 --- /dev/null +++ b/.github/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug Report +about: Create a report to help us improve +title: "[BUG] " +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/feature_request.md b/.github/feature_request.md new file mode 100644 index 0000000..cdca565 --- /dev/null +++ b/.github/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature Request +about: Suggest an idea for this project +title: "[FEATURE] " +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6acb60f --- /dev/null +++ b/.gitignore @@ -0,0 +1,117 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# Virtualenv +venv/ +ENV/ +env/ +.venv/ +.env + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak +venv.bak + +# IDEs +.idea/ +.vscode/ +*.swp +*.swo +*~ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..a7b4cf7 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,122 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that are welcoming, inclusive, and +respectful. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interaction in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. + +[homepage]: https://www.contributor-covenant.org +[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..71f7d4b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,47 @@ +# Contributing to Singularity-AI + +First off, thank you for considering contributing to Singularity-AI! It's people like you that make the open-source community such a great place. + +We welcome any type of contribution, not only code. You can help with: +* **Reporting a bug** +* **Discussing the current state of the code** +* **Submitting a fix** +* **Proposing new features** +* **Becoming a maintainer** + +## We Develop with Github +We use Github to host code, to track issues and feature requests, as well as accept pull requests. + +## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests +Pull requests are the best way to propose changes to the codebase. We actively welcome your pull requests: + +1. Fork the repo and create your branch from `main`. +2. If you've added code that should be tested, add tests. +3. If you've changed APIs, update the documentation. +4. Ensure the test suite passes. +5. Make sure your code lints. +6. Issue that pull request! + +## Any contributions you make will be under the MIT Software License +In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern. + +## Report bugs using Github's [issues](https://github.com/briandk/transcriptase-atom/issues) +We use GitHub issues to track public bugs. Report a bug by [opening a new issue](); it's that easy! + +## Write bug reports with detail, background, and sample code +**Great Bug Reports** tend to have: +- A quick summary and/or background +- Steps to reproduce + - Be specific! + - Give sample code if you can. +- What you expected would happen +- What actually happens +- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) + +People *love* thorough bug reports. I'm not even kidding. + +## Use a Consistent Coding Style +We don't have a strict style guide yet, but we try to follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) for Python code. Please try to follow the style of the existing code. + +## License +By contributing, you agree that your contributions will be licensed under its MIT License. diff --git a/README.md b/README.md index 72bad52..aa1994a 100644 --- a/README.md +++ b/README.md @@ -1 +1,109 @@ -# Singularity-AI \ No newline at end of file +
+

+ โ™พ๏ธ +
+ Singularity-AI +

+

+ Autonomous Software Engineering Assistant +

+

+ Where AI meets infinity. Generate, test, debug, and deploy code with the power of generative AI. +

+
+ +

+ License + Language + Framework + AI +

+ +--- + +## ๐Ÿš€ Introduction + +Singularity-AI is a powerful and intuitive Streamlit application that acts as an autonomous software engineering assistant. It leverages the capabilities of Google's Gemini large language model to provide a seamless experience for generating, testing, debugging, refactoring, and deploying software projects. Whether you're a seasoned developer looking to accelerate your workflow or a beginner learning to code, Singularity-AI is your go-to tool for building high-quality software. + +## โœจ Features + +- **Project Generation:** Describe your project in natural language and watch as Singularity-AI generates a complete, multi-file project structure with production-ready code. +- **Automated Testing:** Automatically run tests for your generated projects to ensure code quality and correctness. +- **Autonomous Debugging:** If tests fail, Singularity-AI can autonomously analyze the errors and attempt to fix the code. +- **Code Refactoring:** Refactor your code for readability, performance, size, or security with a single click. +- **In-depth Code Analysis:** Get detailed explanations of your code, including complexity analysis and suggestions for improvement. +- **Security Scanning:** Perform security analysis on your projects to identify and mitigate potential vulnerabilities. +- **CI/CD and Deployment:** Generate CI/CD configurations for popular platforms like GitHub Actions and create deployment scripts for Docker, Kubernetes, and more. +- **Interactive Dashboard:** Visualize project metrics, health scores, and quality trends over time. + +## ๐Ÿ› ๏ธ Installation & Setup + +Follow these steps to get Singularity-AI up and running on your local machine. + +### 1. Clone the Repository + +```bash +git clone https://github.com/your-username/Singularity-AI.git +cd Singularity-AI +``` + +### 2. Create a Virtual Environment + +It's recommended to use a virtual environment to manage dependencies. + +```bash +python -m venv venv +source venv/bin/activate # On Windows, use `venv\Scripts\activate` +``` + +### 3. Install Dependencies + +Install the required Python packages using pip. + +```bash +pip install -r requirements.txt +``` + +### 4. Set Up Your API Key + +Singularity-AI uses the Google Gemini API. You'll need to get an API key from the [Google AI Studio](https://aistudio.google.com/). + +Once you have your key, create a `.env` file in the root of the project directory by copying the example file: + +```bash +cp .env.example .env +``` + +Now, open the `.env` file and add your Gemini API key: + +``` +GEMINI_API_KEY="YOUR_API_KEY_HERE" +``` + +## ๐Ÿƒโ€โ™€๏ธ How to Run + +With the setup complete, you can run the Streamlit application with a single command: + +```bash +streamlit run src/main.py +``` + +This will start the application, and you can access it in your web browser at `http://localhost:8501`. + +## ๐Ÿ“– How to Use + +1. **Configure Your Project:** Use the sidebar to select the programming language and architecture pattern for your project. +2. **Generate a Project:** In the "Generate" tab, describe the project you want to build and click "Generate Project". +3. **Build and Test:** Once your project is generated, head to the "Build & Test" tab to run build commands and execute tests. +4. **Analyze and Refactor:** Use the "Analysis" tab to get code explanations and the "Build & Test" tab to refactor your code. +5. **Deploy:** In the "Deploy" tab, generate CI/CD configurations, Dockerfiles, and deployment scripts for your project. + +## ๐Ÿ™Œ Contributing + +Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. + +Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for details on how to contribute to the project. + +## ๐Ÿ“œ License + +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. diff --git a/app.py b/app.py deleted file mode 100644 index b744bcb..0000000 --- a/app.py +++ /dev/null @@ -1,1235 +0,0 @@ -import streamlit as st -import google.generativeai as genai -import os -import tempfile -import zipfile -import subprocess -import json -import time -import ast -import re -from pathlib import Path -from typing import Dict, List, Tuple, Optional -import pandas as pd -import plotly.graph_objects as go -import plotly.express as px -from datetime import datetime -import shutil - -# Page config -st.set_page_config( - page_title="Singularity-AI", - page_icon="โ™พ๏ธ", - layout="wide", - initial_sidebar_state="expanded" -) - -# Custom CSS for Singularity-AI theme -st.markdown(""" - -""", unsafe_allow_html=True) - -class CodeOracle: - def __init__(self, api_key: str): - self.api_key = api_key - genai.configure(api_key=api_key) - self.model = genai.GenerativeModel('gemini-2.5-flash') - self.projects = {} - - def generate_project(self, prompt: str, language: str, architecture: str = "standard") -> Dict: - """Generate a complete project from natural language prompt""" - - system_prompt = f""" - You are CodeOracle, an expert software engineer. Generate a complete, production-ready {language} project based on the user's requirements. - - CRITICAL REQUIREMENTS: - 1. Create a multi-file project structure with proper organization - 2. Include all necessary files: source code, tests, README.md, requirements/package files, .gitignore - 3. Write actual working code, not pseudocode or placeholders - 4. Include comprehensive error handling and logging - 5. Follow {language} best practices and conventions - 6. Make the code modular and well-documented - 7. Include unit tests and integration tests - 8. Add security considerations where applicable - - Project Requirements: {prompt} - Target Language: {language} - Architecture Pattern: {architecture} - - Return the response as a JSON object with this exact structure: - {{ - "project_name": "project-name", - "description": "Brief project description", - "files": {{ - "filename1.ext": "file content here", - "filename2.ext": "file content here", - "tests/test_file.ext": "test content here", - "README.md": "comprehensive readme", - ".gitignore": "appropriate gitignore for {language}" - }}, - "dependencies": ["list", "of", "dependencies"], - "build_commands": ["command1", "command2"], - "run_commands": ["command1", "command2"], - "test_commands": ["test command"], - "architecture_notes": "explanation of the chosen architecture" - }} - """ - - try: - response = self.model.generate_content(system_prompt) - - # Parse JSON response - json_start = response.text.find('{') - json_end = response.text.rfind('}') + 1 - json_str = response.text[json_start:json_end] - - project_data = json.loads(json_str) - return project_data - - except Exception as e: - st.error(f"Generation failed: {str(e)}") - return None - - def run_tests(self, project_path: str, language: str, test_commands: List[str]) -> Dict: - """Run automated tests and return results""" - results = { - "success": False, - "output": "", - "errors": "", - "coverage": 0, - "failed_tests": [] - } - - try: - os.chdir(project_path) - - for cmd in test_commands: - process = subprocess.run( - cmd.split(), - capture_output=True, - text=True, - timeout=30 - ) - - results["output"] += f"Command: {cmd}\n" - results["output"] += process.stdout - - if process.returncode != 0: - results["errors"] += process.stderr - results["failed_tests"].append(cmd) - else: - results["success"] = True - - except subprocess.TimeoutExpired: - results["errors"] = "Test execution timed out" - except Exception as e: - results["errors"] = str(e) - - return results - - def debug_and_fix(self, project_data: Dict, test_results: Dict, max_iterations: int = 3) -> Dict: - """Autonomous debugging loop""" - - debug_prompt = f""" - The following project has failing tests. Analyze the errors and fix the code: - - Project Structure: {list(project_data['files'].keys())} - Test Errors: {test_results['errors']} - Failed Commands: {test_results['failed_tests']} - - Current Code Files: - {json.dumps(project_data['files'], indent=2)} - - Fix the issues and return the corrected files in the same JSON structure. - Focus on: - 1. Syntax errors - 2. Import/dependency issues - 3. Logic errors causing test failures - 4. Missing error handling - - Return only the corrected files that need changes in this format: - {{ - "fixed_files": {{ - "filename": "corrected content" - }}, - "fix_explanation": "What was fixed and why" - }} - """ - - try: - response = self.model.generate_content(debug_prompt) - json_start = response.text.find('{') - json_end = response.text.rfind('}') + 1 - json_str = response.text[json_start:json_end] - - fix_data = json.loads(json_str) - - # Apply fixes - for filename, content in fix_data.get("fixed_files", {}).items(): - project_data["files"][filename] = content - - return { - "success": True, - "explanation": fix_data.get("fix_explanation", ""), - "updated_project": project_data - } - - except Exception as e: - return {"success": False, "error": str(e)} - - def refactor_code(self, project_data: Dict, refactor_type: str) -> Dict: - """Refactor code for different objectives""" - - refactor_prompts = { - "readability": "Refactor for maximum readability and maintainability", - "performance": "Optimize for performance and efficiency", - "size": "Minimize code size and bundle size", - "security": "Enhance security and add security best practices" - } - - prompt = f""" - {refactor_prompts[refactor_type]} for this project: - - {json.dumps(project_data['files'], indent=2)} - - Return the refactored files in JSON format with explanations. - """ - - try: - response = self.model.generate_content(prompt) - # Parse and return refactored code - return {"success": True, "refactored": response.text} - except Exception as e: - return {"success": False, "error": str(e)} - - def explain_code(self, code: str, language: str) -> str: - """Provide detailed code explanation""" - - prompt = f""" - Explain this {language} code line by line with: - 1. What each function/class does - 2. Time/space complexity analysis - 3. Alternative approaches - 4. How a senior developer would improve it - 5. Potential issues or edge cases - - Code: - {code} - """ - - try: - response = self.model.generate_content(prompt) - return response.text - except Exception as e: - return f"Explanation failed: {str(e)}" - - def security_scan(self, project_data: Dict, language: str) -> Dict: - """Perform security analysis""" - - prompt = f""" - Perform a comprehensive security analysis of this {language} project using OWASP guidelines: - - {json.dumps(project_data['files'], indent=2)} - - Identify: - 1. Security vulnerabilities - 2. Input validation issues - 3. Authentication/authorization flaws - 4. Data exposure risks - 5. Dependency vulnerabilities - - Return findings with severity levels and suggested fixes. - """ - - try: - response = self.model.generate_content(prompt) - return {"success": True, "report": response.text} - except Exception as e: - return {"success": False, "error": str(e)} - - def generate_cicd(self, project_data: Dict, language: str, platform: str) -> str: - """Generate CI/CD configuration""" - - prompt = f""" - Generate {platform} CI/CD configuration for this {language} project: - - Project: {project_data['project_name']} - Dependencies: {project_data['dependencies']} - Build Commands: {project_data['build_commands']} - Test Commands: {project_data['test_commands']} - - Include: - 1. Build pipeline - 2. Test automation - 3. Security scanning - 4. Deployment steps - 5. Environment management - - Platform: {platform} - """ - - try: - response = self.model.generate_content(prompt) - return response.text - except Exception as e: - return f"CI/CD generation failed: {str(e)}" - -def create_project_files(project_data: Dict, base_path: str): - """Create actual files from project data""" - # Ensure base directory exists - os.makedirs(base_path, exist_ok=True) - - for filename, content in project_data["files"].items(): - file_path = os.path.join(base_path, filename) - - # Create directory if filename contains subdirectories - file_dir = os.path.dirname(file_path) - if file_dir and file_dir != base_path: - os.makedirs(file_dir, exist_ok=True) - - try: - with open(file_path, 'w', encoding='utf-8') as f: - f.write(content) - except Exception as e: - st.error(f"Failed to create file {filename}: {str(e)}") - continue - -def create_zip_download(project_data: Dict) -> bytes: - """Create downloadable zip file""" - zip_buffer = tempfile.NamedTemporaryFile(delete=False, suffix='.zip') - - with zipfile.ZipFile(zip_buffer.name, 'w', zipfile.ZIP_DEFLATED) as zip_file: - for filename, content in project_data["files"].items(): - zip_file.writestr(filename, content) - - with open(zip_buffer.name, 'rb') as f: - zip_data = f.read() - - os.unlink(zip_buffer.name) - return zip_data - -# Initialize session state variables to prevent reruns -def init_session_state(): - """Initialize all session state variables""" - if 'oracle' not in st.session_state: - st.session_state.oracle = None - if 'current_project' not in st.session_state: - st.session_state.current_project = None - if 'test_results' not in st.session_state: - st.session_state.test_results = None - if 'generation_status' not in st.session_state: - st.session_state.generation_status = None - if 'build_output' not in st.session_state: - st.session_state.build_output = None - if 'security_report' not in st.session_state: - st.session_state.security_report = None - if 'cicd_configs' not in st.session_state: - st.session_state.cicd_configs = {} - if 'refactor_results' not in st.session_state: - st.session_state.refactor_results = {} - if 'explanations' not in st.session_state: - st.session_state.explanations = {} - if 'project_metrics' not in st.session_state: - st.session_state.project_metrics = {} - -def main(): - # Initialize session state - init_session_state() - - # Title and header with new theme - st.markdown('

โ™พ๏ธ Singularity-AI

', unsafe_allow_html=True) - st.markdown('
Where AI meets infinity โ™พ๏ธ
', unsafe_allow_html=True) - - # Sidebar configuration - with st.sidebar: - st.markdown("### โš™๏ธ Configuration") - - # API Key input - api_key = st.text_input( - "๐Ÿ”‘ Gemini API Key", - type="password", - help="Enter your Google Gemini API key", - key="api_key_input" - ) - - if not api_key: - st.error("โš ๏ธ Please enter your Gemini API key to continue") - st.stop() - - # Initialize CodeOracle only once - if st.session_state.oracle is None: - st.session_state.oracle = CodeOracle(api_key) - st.success("โœ… Singularity-AI Initialized!") - - # Language selection - language = st.selectbox( - "๐Ÿ’ป Programming Language", - ["Python", "JavaScript", "TypeScript", "Go", "Rust", "Java", "Kotlin", "C++"], - key="language_select" - ) - - # Architecture pattern - architecture = st.selectbox( - "๐Ÿ—๏ธ Architecture Pattern", - ["Standard", "MVC", "Microservices", "Serverless", "Clean Architecture", "Hexagonal"], - key="architecture_select" - ) - - # Advanced settings - st.markdown("### ๐Ÿ”ฌ Advanced Settings") - max_debug_iterations = st.slider("Max Debug Iterations", 1, 10, 3, key="debug_iter") - auto_test = st.checkbox("Auto-run tests", value=True, key="auto_test") - auto_debug = st.checkbox("Auto-debug failures", value=True, key="auto_debug") - - # Main interface tabs - tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs([ - "๐Ÿš€ Generate", "๐Ÿ”ง Build & Test", "๐Ÿ” Analysis", "๐Ÿ“Š Dashboard", "๐Ÿ›ก๏ธ Security", "๐Ÿš€ Deploy" - ]) - - with tab1: - st.markdown("### ๐ŸŽฏ Project Generator") - - # Project generation form - col1, col2 = st.columns([3, 1]) - - with col1: - prompt = st.text_area( - "๐Ÿ“ Describe your project:", - #value=default_prompt, - placeholder="Build a REST API for a todo app with user authentication, SQLite database, and CRUD operations", - height=120, - key="project_prompt" - ) - - with col2: - template = st.selectbox( - "โšก Quick Templates", - ["Custom", "Web App + Auth", "REST API", "ML Service", "CLI Tool", "Microservice"], - key="template_select" - ) - - # Template auto-fill - # Template auto-fill - set default value based on template - template_prompts = { - "Custom": "", - "Web App + Auth": "Create a modern web application with user authentication, responsive design, and database integration", - "REST API": "Build a RESTful API with CRUD operations, authentication, and comprehensive documentation", - "ML Service": "Create a machine learning inference service with model loading, prediction endpoints, and monitoring", - "CLI Tool": "Build a command-line tool with argument parsing, configuration management, and user-friendly output", - "Microservice": "Create a microservice with health checks, logging, metrics, and containerization" - } - - # Set the default prompt value based on template selection - default_prompt = template_prompts.get(template, "") - - col1, col2 = st.columns(2) - with col1: - if st.button("๐Ÿง™โ€โ™‚๏ธ Generate Project", type="primary", key="generate_btn"): - if prompt: - with st.spinner("๐Ÿ”ฎ Singularity-AI is crafting your project..."): - project_data = st.session_state.oracle.generate_project(prompt, language, architecture) - - if project_data: - st.session_state.current_project = project_data - st.session_state.generation_status = "success" - - # Calculate initial metrics - total_lines = sum(len(content.split('\n')) for content in project_data['files'].values()) - st.session_state.project_metrics = { - 'total_files': len(project_data['files']), - 'total_lines': total_lines, - 'avg_lines_per_file': round(total_lines/len(project_data['files'])), - 'dependencies': len(project_data.get('dependencies', [])) - } - else: - st.session_state.generation_status = "error" - else: - st.error("โš ๏ธ Please provide a project description") - - # Display project overview (persistent) - if st.session_state.current_project and st.session_state.generation_status == "success": - project = st.session_state.current_project - - st.markdown('
โœจ Project generated successfully!
', unsafe_allow_html=True) - - st.markdown("### ๐Ÿ“‹ Project Overview") - col1, col2 = st.columns(2) - - with col1: - st.markdown(f"**๐Ÿท๏ธ Name:** `{project['project_name']}`") - st.markdown(f"**๐Ÿ’ป Language:** `{language}`") - st.markdown(f"**๐Ÿ“ Files:** `{st.session_state.project_metrics['total_files']}`") - - with col2: - st.markdown(f"**๐Ÿ“ฆ Dependencies:** `{st.session_state.project_metrics['dependencies']}`") - st.markdown(f"**๐Ÿ—๏ธ Architecture:** `{architecture}`") - st.markdown(f"**๐Ÿ“ Lines:** `{st.session_state.project_metrics['total_lines']}`") - - st.markdown(f"**๐Ÿ“ Description:** {project['description']}") - - # File browser - st.markdown("### ๐Ÿ“ Generated Files") - selected_file = st.selectbox( - "View file:", - list(project['files'].keys()), - key="file_browser" - ) - - if selected_file: - file_ext = selected_file.split('.')[-1] if '.' in selected_file else 'text' - st.code(project['files'][selected_file], language=file_ext) - - # Download button - col1, col2 = st.columns(2) - with col1: - zip_data = create_zip_download(project) - st.download_button( - label="๐Ÿ“ฆ Download Project ZIP", - data=zip_data, - file_name=f"{project['project_name']}.zip", - mime="application/zip", - key="download_zip" - ) - - with tab2: - st.markdown("### ๐Ÿ”ง Build & Test Pipeline") - - if not st.session_state.current_project: - st.markdown('
โ„น๏ธ Generate a project first to see build and test options
', unsafe_allow_html=True) - else: - project = st.session_state.current_project - - col1, col2, col3 = st.columns(3) - - with col1: - if st.button("๐Ÿ”จ Build Project", key="build_btn"): - with st.spinner("๐Ÿ—๏ธ Building project..."): - # Create temporary directory - temp_dir = tempfile.mkdtemp() - create_project_files(project, temp_dir) - - # Run build commands - build_success = True - build_output = "" - - for cmd in project.get('build_commands', []): - try: - result = subprocess.run( - cmd.split(), - cwd=temp_dir, - capture_output=True, - text=True, - timeout=60 - ) - build_output += f"$ {cmd}\n{result.stdout}\n" - if result.returncode != 0: - build_success = False - build_output += f"Error: {result.stderr}\n" - except Exception as e: - build_success = False - build_output += f"Build failed: {str(e)}\n" - - st.session_state.build_output = { - "success": build_success, - "output": build_output - } - - # Display build results (persistent) - if st.session_state.build_output: - if st.session_state.build_output["success"]: - st.markdown('
โœ… Build successful!
', unsafe_allow_html=True) - else: - st.markdown('
โŒ Build failed
', unsafe_allow_html=True) - - st.code(st.session_state.build_output["output"], language="bash") - - with col2: - if st.button("๐Ÿงช Run Tests", key="test_btn"): - with st.spinner("๐Ÿ”ฌ Running tests..."): - temp_dir = tempfile.mkdtemp() - create_project_files(project, temp_dir) - - test_results = st.session_state.oracle.run_tests( - temp_dir, - language, - project.get('test_commands', []) - ) - - st.session_state.test_results = test_results - - # Display test results (persistent) - if st.session_state.test_results: - if st.session_state.test_results["success"]: - st.markdown('
โœ… All tests passed!
', unsafe_allow_html=True) - else: - st.markdown('
โŒ Some tests failed
', unsafe_allow_html=True) - - st.code(st.session_state.test_results["output"], language="bash") - - if st.session_state.test_results["errors"]: - st.error("Test Errors:") - st.code(st.session_state.test_results["errors"], language="bash") - - with col3: - if st.button("๐Ÿ”ง Auto-Debug", key="debug_btn"): - if st.session_state.test_results and not st.session_state.test_results["success"]: - with st.spinner("๐Ÿค– Auto-debugging..."): - debug_result = st.session_state.oracle.debug_and_fix( - project, - st.session_state.test_results, - max_debug_iterations - ) - - if debug_result["success"]: - st.session_state.current_project = debug_result["updated_project"] - st.success("๐Ÿ”ง Auto-debug completed!") - st.markdown(debug_result["explanation"]) - else: - st.error(f"Auto-debug failed: {debug_result['error']}") - else: - st.info("No failing tests to debug") - - # Refactoring options - st.markdown("### ๐Ÿ”„ Refactoring Options") - refactor_col1, refactor_col2, refactor_col3, refactor_col4 = st.columns(4) - - with refactor_col1: - if st.button("๐Ÿ“š Readability", key="refactor_readability"): - with st.spinner("๐Ÿ“– Refactoring for readability..."): - result = st.session_state.oracle.refactor_code(project, "readability") - if result["success"]: - st.session_state.refactor_results["readability"] = result["refactored"] - - # Display readability refactor result (persistent) - if "readability" in st.session_state.refactor_results: - with st.expander("๐Ÿ“š Readability Refactor Result"): - st.markdown(st.session_state.refactor_results["readability"]) - - with refactor_col2: - if st.button("โšก Performance", key="refactor_performance"): - with st.spinner("๐Ÿš€ Optimizing performance..."): - result = st.session_state.oracle.refactor_code(project, "performance") - if result["success"]: - st.session_state.refactor_results["performance"] = result["refactored"] - - # Display performance refactor result (persistent) - if "performance" in st.session_state.refactor_results: - with st.expander("โšก Performance Refactor Result"): - st.markdown(st.session_state.refactor_results["performance"]) - - with refactor_col3: - if st.button("๐Ÿ“ฆ Size", key="refactor_size"): - with st.spinner("๐Ÿ“‰ Minimizing size..."): - result = st.session_state.oracle.refactor_code(project, "size") - if result["success"]: - st.session_state.refactor_results["size"] = result["refactored"] - - # Display size refactor result (persistent) - if "size" in st.session_state.refactor_results: - with st.expander("๐Ÿ“ฆ Size Refactor Result"): - st.markdown(st.session_state.refactor_results["size"]) - - with refactor_col4: - if st.button("๐Ÿ›ก๏ธ Security", key="refactor_security"): - with st.spinner("๐Ÿ”’ Enhancing security..."): - result = st.session_state.oracle.refactor_code(project, "security") - if result["success"]: - st.session_state.refactor_results["security"] = result["refactored"] - - # Display security refactor result (persistent) - if "security" in st.session_state.refactor_results: - with st.expander("๐Ÿ›ก๏ธ Security Refactor Result"): - st.markdown(st.session_state.refactor_results["security"]) - - with tab3: - st.markdown("### ๐Ÿ” Code Analysis & Insights") - - if not st.session_state.current_project: - st.markdown('
โ„น๏ธ Generate a project first to see analysis options
', unsafe_allow_html=True) - else: - project = st.session_state.current_project - - # Code explanation - st.markdown("### ๐Ÿ“– Explain Code") - explain_file = st.selectbox( - "Select file to explain:", - list(project['files'].keys()), - key="explain_file_select" - ) - - if st.button("๐Ÿ” Explain This File", key="explain_btn"): - with st.spinner("๐Ÿง  Analyzing code..."): - explanation = st.session_state.oracle.explain_code( - project['files'][explain_file], - language - ) - st.session_state.explanations[explain_file] = explanation - - # Display explanation (persistent) - if explain_file in st.session_state.explanations: - with st.expander(f"๐Ÿ“– Explanation: {explain_file}"): - st.markdown(st.session_state.explanations[explain_file]) - - # Architecture visualization - st.markdown("### ๐Ÿ—๏ธ Architecture Overview") - - col1, col2 = st.columns(2) - with col1: - if st.button("๐Ÿ“Š Visualize Architecture", key="viz_arch_btn"): - # Create a simple architecture diagram - files = list(project['files'].keys()) - file_types = {} - - for file in files: - ext = file.split('.')[-1] if '.' in file else 'other' - file_types[ext] = file_types.get(ext, 0) + 1 - - # Store visualization data in session state - st.session_state.arch_viz_data = file_types - - # Display architecture visualization (persistent) - if hasattr(st.session_state, 'arch_viz_data'): - # Create pie chart of file types - fig = px.pie( - values=list(st.session_state.arch_viz_data.values()), - names=list(st.session_state.arch_viz_data.keys()), - title="Project File Distribution", - color_discrete_sequence=px.colors.qualitative.Set3 - ) - fig.update_layout( - plot_bgcolor='rgba(0,0,0,0)', - paper_bgcolor='rgba(0,0,0,0)', - font_color='white' - ) - st.plotly_chart(fig, use_container_width=True) - - # Dependency graph (simplified) - st.markdown("### ๐Ÿ“ฆ Dependencies") - deps = project.get('dependencies', []) - if deps: - dep_df = pd.DataFrame({'Dependency': deps, 'Type': ['External'] * len(deps)}) - st.dataframe(dep_df, use_container_width=True) - else: - st.info("No external dependencies found") - - # Code metrics - st.markdown("### ๐Ÿ“ Code Metrics") - - st.markdown("### ๐Ÿ“ Code Metrics") - - if hasattr(st.session_state, 'project_metrics') and st.session_state.project_metrics: - metrics = st.session_state.project_metrics - col1, col2, col3, col4 = st.columns(4) - col1.metric("Total Files", metrics['total_files']) - col2.metric("Total Lines", metrics['total_lines']) - col3.metric("Avg Lines/File", metrics['avg_lines_per_file']) - col4.metric("Dependencies", metrics['dependencies']) - elif st.session_state.current_project: - # Fallback calculation if metrics not available - project = st.session_state.current_project - total_files = len(project['files']) - total_lines = sum(len(content.split('\n')) for content in project['files'].values()) - avg_lines = round(total_lines/total_files) if total_files > 0 else 0 - dependencies = len(project.get('dependencies', [])) - - col1, col2, col3, col4 = st.columns(4) - col1.metric("Total Files", total_files) - col2.metric("Total Lines", total_lines) - col3.metric("Avg Lines/File", avg_lines) - col4.metric("Dependencies", dependencies) - - with tab4: - st.markdown("### ๐Ÿ“Š Project Health Dashboard") - - if not st.session_state.current_project: - st.markdown('
โ„น๏ธ Generate a project first to see the dashboard
', unsafe_allow_html=True) - else: - project = st.session_state.current_project - - # Health score calculation (mock) - health_score = 85 # This would be calculated based on various metrics - - col1, col2, col3 = st.columns(3) - - with col1: - st.metric("๐Ÿฅ Health Score", f"{health_score}%", "5%") - with col2: - test_coverage = "78%" if st.session_state.test_results and st.session_state.test_results["success"] else "0%" - st.metric("๐Ÿงช Test Coverage", test_coverage, "12%") - with col3: - security_rating = "A-" if "security" in st.session_state.refactor_results else "C" - st.metric("๐Ÿ›ก๏ธ Security Rating", security_rating, "0") - - # Project timeline (mock data) - st.markdown("### ๐Ÿ•’ Project Timeline") - timeline_events = [] - if st.session_state.current_project: - timeline_events.append(('Generated', datetime.now().strftime('%H:%M:%S'), 'โœ…')) - if st.session_state.build_output: - status = 'โœ…' if st.session_state.build_output["success"] else 'โŒ' - timeline_events.append(('Built', datetime.now().strftime('%H:%M:%S'), status)) - if st.session_state.test_results: - status = 'โœ…' if st.session_state.test_results["success"] else 'โŒ' - timeline_events.append(('Tested', datetime.now().strftime('%H:%M:%S'), status)) - if st.session_state.security_report: - timeline_events.append(('Secured', datetime.now().strftime('%H:%M:%S'), 'โœ…')) - - if timeline_events: - timeline_data = pd.DataFrame(timeline_events, columns=['Event', 'Timestamp', 'Status']) - st.dataframe(timeline_data, use_container_width=True) - - # Code quality trends (mock chart) - st.markdown("### ๐Ÿ“ˆ Quality Trends") - - # Generate mock trend data - dates = pd.date_range(start='2024-01-01', end='2024-12-31', freq='M') - quality_data = pd.DataFrame({ - 'Date': dates, - 'Code Quality': [75 + i*2 + (i%3)*5 for i in range(len(dates))], - 'Test Coverage': [60 + i*1.5 + (i%2)*3 for i in range(len(dates))], - 'Security Score': [70 + i*1.8 + (i%4)*4 for i in range(len(dates))] - }) - - fig = px.line( - quality_data, - x='Date', - y=['Code Quality', 'Test Coverage', 'Security Score'], - title="Project Health Over Time" - ) - fig.update_layout( - plot_bgcolor='rgba(0,0,0,0)', - paper_bgcolor='rgba(0,0,0,0)', - font_color='white' - ) - st.plotly_chart(fig, use_container_width=True) - - with tab5: - st.markdown("### ๐Ÿ›ก๏ธ Security Analysis") - - if not st.session_state.current_project: - st.markdown('
โ„น๏ธ Generate a project first to run security analysis
', unsafe_allow_html=True) - else: - project = st.session_state.current_project - - if st.button("๐Ÿ” Run Security Scan", key="security_scan_btn"): - with st.spinner("๐Ÿ›ก๏ธ Scanning for security vulnerabilities..."): - security_result = st.session_state.oracle.security_scan(project, language) - st.session_state.security_report = security_result - - # Display security report (persistent) - if st.session_state.security_report: - if st.session_state.security_report["success"]: - st.markdown("### ๐Ÿ›ก๏ธ Security Report") - st.markdown(st.session_state.security_report["report"]) - else: - st.error(f"Security scan failed: {st.session_state.security_report['error']}") - - # Security checklist - st.markdown("### โœ… Security Checklist") - - security_items = [ - "Input validation implemented", - "Authentication mechanisms in place", - "Authorization checks present", - "SQL injection prevention", - "XSS protection enabled", - "CSRF tokens implemented", - "Secure headers configured", - "Dependency vulnerabilities checked" - ] - - for i, item in enumerate(security_items): - st.checkbox(item, value=False, key=f"security_check_{i}") - - with tab6: - st.markdown("### ๐Ÿš€ Deployment & CI/CD") - - if not st.session_state.current_project: - st.markdown('
โ„น๏ธ Generate a project first to see deployment options
', unsafe_allow_html=True) - else: - project = st.session_state.current_project - - # CI/CD platform selection - col1, col2 = st.columns(2) - - with col1: - st.markdown("### ๐Ÿ”„ CI/CD Configuration") - cicd_platform = st.selectbox( - "Platform:", - ["GitHub Actions", "GitLab CI", "CircleCI", "Jenkins"], - key="cicd_platform_select" - ) - - if st.button("Generate CI/CD Config", key="generate_cicd_btn"): - with st.spinner("โš™๏ธ Generating CI/CD configuration..."): - cicd_config = st.session_state.oracle.generate_cicd( - project, language, cicd_platform - ) - st.session_state.cicd_configs[cicd_platform] = cicd_config - - # Display CI/CD config (persistent) - if cicd_platform in st.session_state.cicd_configs: - st.code(st.session_state.cicd_configs[cicd_platform], language="yaml") - - # Download CI/CD config - st.download_button( - label="๐Ÿ“ฅ Download CI/CD Config", - data=st.session_state.cicd_configs[cicd_platform], - file_name=f"{cicd_platform.lower().replace(' ', '_')}.yml", - mime="text/yaml", - key=f"download_cicd_{cicd_platform}" - ) - - with col2: - st.markdown("### ๐Ÿณ Containerization") - - if st.button("Generate Dockerfile", key="generate_dockerfile_btn"): - dockerfile_prompt = f""" - Generate a production-ready Dockerfile for this {language} project: - - Project: {project['project_name']} - Dependencies: {project.get('dependencies', [])} - Build Commands: {project.get('build_commands', [])} - Run Commands: {project.get('run_commands', [])} - - Include: - - Multi-stage build - - Security best practices - - Optimized layer caching - - Non-root user - - Health checks - """ - - with st.spinner("๐Ÿณ Generating Dockerfile..."): - try: - response = st.session_state.oracle.model.generate_content(dockerfile_prompt) - st.session_state.dockerfile_content = response.text - except Exception as e: - st.error(f"Dockerfile generation failed: {str(e)}") - - # Display Dockerfile (persistent) - if hasattr(st.session_state, 'dockerfile_content'): - st.code(st.session_state.dockerfile_content, language="dockerfile") - - st.download_button( - label="๐Ÿ“ฅ Download Dockerfile", - data=st.session_state.dockerfile_content, - file_name="Dockerfile", - mime="text/plain", - key="download_dockerfile" - ) - - # Deployment scripts - st.markdown("### ๐ŸŒ Deployment Scripts") - - deployment_type = st.selectbox( - "Deployment Target:", - ["Docker Compose", "Kubernetes", "AWS ECS", "Google Cloud Run", "Azure Container Apps"], - key="deployment_type_select" - ) - - if st.button("Generate Deployment Script", key="generate_deploy_btn"): - deploy_prompt = f""" - Generate deployment configuration for {deployment_type} for this project: - - Project: {project['project_name']} - Language: {language} - Dependencies: {project.get('dependencies', [])} - Build Commands: {project.get('build_commands', [])} - Run Commands: {project.get('run_commands', [])} - - Include: - - Service definitions - - Environment variables - - Resource limits - - Health checks - - Networking configuration - - Scaling policies - - Monitoring setup - """ - - with st.spinner(f"๐Ÿš€ Generating {deployment_type} configuration..."): - try: - response = st.session_state.oracle.model.generate_content(deploy_prompt) - if 'deploy_configs' not in st.session_state: - st.session_state.deploy_configs = {} - st.session_state.deploy_configs[deployment_type] = response.text - except Exception as e: - st.error(f"Deployment configuration generation failed: {str(e)}") - - # Display deployment config (persistent) - if hasattr(st.session_state, 'deploy_configs') and deployment_type in st.session_state.deploy_configs: - st.code(st.session_state.deploy_configs[deployment_type], language="yaml") - - # Determine file extension based on deployment type - file_extensions = { - "Docker Compose": "docker-compose.yml", - "Kubernetes": "k8s-deployment.yaml", - "AWS ECS": "ecs-task-definition.json", - "Google Cloud Run": "cloudrun-service.yaml", - "Azure Container Apps": "containerapp.yaml" - } - - filename = file_extensions.get(deployment_type, "deployment.yaml") - - st.download_button( - label=f"๐Ÿ“ฅ Download {deployment_type} Config", - data=st.session_state.deploy_configs[deployment_type], - file_name=filename, - mime="text/yaml", - key=f"download_deploy_{deployment_type}" - ) - - # Environment management - st.markdown("### ๐Ÿ”ง Environment Configuration") - - env_type = st.selectbox( - "Environment Type:", - ["Development", "Staging", "Production"], - key="env_type_select" - ) - - if st.button("Generate Environment Config", key="generate_env_btn"): - env_prompt = f""" - Generate environment configuration for {env_type} environment: - - Project: {project['project_name']} - Language: {language} - - Include appropriate settings for {env_type}: - - Environment variables - - Database configurations - - Logging levels - - Security settings - - Performance optimizations - - Monitoring configurations - """ - - with st.spinner(f"โš™๏ธ Generating {env_type} environment config..."): - try: - response = st.session_state.oracle.model.generate_content(env_prompt) - if 'env_configs' not in st.session_state: - st.session_state.env_configs = {} - st.session_state.env_configs[env_type] = response.text - except Exception as e: - st.error(f"Environment configuration generation failed: {str(e)}") - - # Display environment config (persistent) - if hasattr(st.session_state, 'env_configs') and env_type in st.session_state.env_configs: - st.code(st.session_state.env_configs[env_type], language="bash") - - st.download_button( - label=f"๐Ÿ“ฅ Download {env_type} Config", - data=st.session_state.env_configs[env_type], - file_name=f".env.{env_type.lower()}", - mime="text/plain", - key=f"download_env_{env_type}" - ) - - # Footer with new theme - st.markdown("---") - st.markdown( - """ -
-

โ™พ๏ธ Singularity-AI - Where AI meets infinity

-

Autonomous Software Engineering Assistant

-

Powered by Google Gemini โ€ข Built with Streamlit โ€ข Enhanced with infinite possibilities

-
โ™พ๏ธ
-
- """, - unsafe_allow_html=True - ) - -if __name__ == "__main__": - main() diff --git a/requirements.txt b/requirements.txt index 0de3097..0c7b718 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ streamlit google-generativeai pandas plotly +python-dotenv diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..1b464b5 --- /dev/null +++ b/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Install dependencies +pip install -r requirements.txt + +# Run the Streamlit application +streamlit run src/main.py diff --git a/src/code_oracle.py b/src/code_oracle.py new file mode 100644 index 0000000..23b34cd --- /dev/null +++ b/src/code_oracle.py @@ -0,0 +1,251 @@ +import streamlit as st +import google.generativeai as genai +import os +import subprocess +import json +from typing import Dict, List + +class CodeOracle: + def __init__(self, api_key: str): + self.api_key = api_key + genai.configure(api_key=api_key) + self.model = genai.GenerativeModel('gemini-2.5-flash') + self.projects = {} + + def generate_project(self, prompt: str, language: str, architecture: str = "standard") -> Dict: + """Generate a complete project from natural language prompt""" + + system_prompt = f""" + You are CodeOracle, an expert software engineer. Generate a complete, production-ready {language} project based on the user's requirements. + + CRITICAL REQUIREMENTS: + 1. Create a multi-file project structure with proper organization + 2. Include all necessary files: source code, tests, README.md, requirements/package files, .gitignore + 3. Write actual working code, not pseudocode or placeholders + 4. Include comprehensive error handling and logging + 5. Follow {language} best practices and conventions + 6. Make the code modular and well-documented + 7. Include unit tests and integration tests + 8. Add security considerations where applicable + + Project Requirements: {prompt} + Target Language: {language} + Architecture Pattern: {architecture} + + Return the response as a JSON object with this exact structure: + {{ + "project_name": "project-name", + "description": "Brief project description", + "files": {{ + "filename1.ext": "file content here", + "filename2.ext": "file content here", + "tests/test_file.ext": "test content here", + "README.md": "comprehensive readme", + ".gitignore": "appropriate gitignore for {language}" + }}, + "dependencies": ["list", "of", "dependencies"], + "build_commands": ["command1", "command2"], + "run_commands": ["command1", "command2"], + "test_commands": ["test command"], + "architecture_notes": "explanation of the chosen architecture" + }} + """ + + try: + response = self.model.generate_content(system_prompt) + + # Parse JSON response + json_start = response.text.find('{') + json_end = response.text.rfind('}') + 1 + json_str = response.text[json_start:json_end] + + project_data = json.loads(json_str) + return project_data + + except Exception as e: + st.error(f"Generation failed: {str(e)}") + return None + + def run_tests(self, project_path: str, language: str, test_commands: List[str]) -> Dict: + """Run automated tests and return results""" + results = { + "success": False, + "output": "", + "errors": "", + "coverage": 0, + "failed_tests": [] + } + + try: + os.chdir(project_path) + + for cmd in test_commands: + process = subprocess.run( + cmd.split(), + capture_output=True, + text=True, + timeout=30 + ) + + results["output"] += f"Command: {cmd}\n" + results["output"] += process.stdout + + if process.returncode != 0: + results["errors"] += process.stderr + results["failed_tests"].append(cmd) + else: + results["success"] = True + + except subprocess.TimeoutExpired: + results["errors"] = "Test execution timed out" + except Exception as e: + results["errors"] = str(e) + + return results + + def debug_and_fix(self, project_data: Dict, test_results: Dict, max_iterations: int = 3) -> Dict: + """Autonomous debugging loop""" + + debug_prompt = f""" + The following project has failing tests. Analyze the errors and fix the code: + + Project Structure: {list(project_data['files'].keys())} + Test Errors: {test_results['errors']} + Failed Commands: {test_results['failed_tests']} + + Current Code Files: + {json.dumps(project_data['files'], indent=2)} + + Fix the issues and return the corrected files in the same JSON structure. + Focus on: + 1. Syntax errors + 2. Import/dependency issues + 3. Logic errors causing test failures + 4. Missing error handling + + Return only the corrected files that need changes in this format: + {{ + "fixed_files": {{ + "filename": "corrected content" + }}, + "fix_explanation": "What was fixed and why" + }} + """ + + try: + response = self.model.generate_content(debug_prompt) + json_start = response.text.find('{') + json_end = response.text.rfind('}') + 1 + json_str = response.text[json_start:json_end] + + fix_data = json.loads(json_str) + + # Apply fixes + for filename, content in fix_data.get("fixed_files", {}).items(): + project_data["files"][filename] = content + + return { + "success": True, + "explanation": fix_data.get("fix_explanation", ""), + "updated_project": project_data + } + + except Exception as e: + return {"success": False, "error": str(e)} + + def refactor_code(self, project_data: Dict, refactor_type: str) -> Dict: + """Refactor code for different objectives""" + + refactor_prompts = { + "readability": "Refactor for maximum readability and maintainability", + "performance": "Optimize for performance and efficiency", + "size": "Minimize code size and bundle size", + "security": "Enhance security and add security best practices" + } + + prompt = f""" + {refactor_prompts[refactor_type]} for this project: + + {json.dumps(project_data['files'], indent=2)} + + Return the refactored files in JSON format with explanations. + """ + + try: + response = self.model.generate_content(prompt) + # Parse and return refactored code + return {"success": True, "refactored": response.text} + except Exception as e: + return {"success": False, "error": str(e)} + + def explain_code(self, code: str, language: str) -> str: + """Provide detailed code explanation""" + + prompt = f""" + Explain this {language} code line by line with: + 1. What each function/class does + 2. Time/space complexity analysis + 3. Alternative approaches + 4. How a senior developer would improve it + 5. Potential issues or edge cases + + Code: + {code} + """ + + try: + response = self.model.generate_content(prompt) + return response.text + except Exception as e: + return f"Explanation failed: {str(e)}" + + def security_scan(self, project_data: Dict, language: str) -> Dict: + """Perform security analysis""" + + prompt = f""" + Perform a comprehensive security analysis of this {language} project using OWASP guidelines: + + {json.dumps(project_data['files'], indent=2)} + + Identify: + 1. Security vulnerabilities + 2. Input validation issues + 3. Authentication/authorization flaws + 4. Data exposure risks + 5. Dependency vulnerabilities + + Return findings with severity levels and suggested fixes. + """ + + try: + response = self.model.generate_content(prompt) + return {"success": True, "report": response.text} + except Exception as e: + return {"success": False, "error": str(e)} + + def generate_cicd(self, project_data: Dict, language: str, platform: str) -> str: + """Generate CI/CD configuration""" + + prompt = f""" + Generate {platform} CI/CD configuration for this {language} project: + + Project: {project_data['project_name']} + Dependencies: {project_data['dependencies']} + Build Commands: {project_data['build_commands']} + Test Commands: {project_data['test_commands']} + + Include: + 1. Build pipeline + 2. Test automation + 3. Security scanning + 4. Deployment steps + 5. Environment management + + Platform: {platform} + """ + + try: + response = self.model.generate_content(prompt) + return response.text + except Exception as e: + return f"CI/CD generation failed: {str(e)}" diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..6b97a1d --- /dev/null +++ b/src/main.py @@ -0,0 +1,145 @@ +import streamlit as st +import os +import tempfile +import subprocess +from dotenv import load_dotenv +from src.code_oracle import CodeOracle +from src.ui import ( + setup_page_config, + load_custom_css, + render_sidebar, + render_main_content, + render_generate_tab, + render_project_overview, + render_build_test_tab, + render_analysis_tab, + render_dashboard_tab, + render_security_tab, + render_deploy_tab, + render_footer +) +from src.utils import create_project_files + +def init_session_state(): + """Initialize all session state variables""" + if 'oracle' not in st.session_state: + st.session_state.oracle = None + if 'current_project' not in st.session_state: + st.session_state.current_project = None + if 'test_results' not in st.session_state: + st.session_state.test_results = None + if 'generation_status' not in st.session_state: + st.session_state.generation_status = None + if 'build_output' not in st.session_state: + st.session_state.build_output = None + if 'security_report' not in st.session_state: + st.session_state.security_report = None + if 'cicd_configs' not in st.session_state: + st.session_state.cicd_configs = {} + if 'refactor_results' not in st.session_state: + st.session_state.refactor_results = {} + if 'explanations' not in st.session_state: + st.session_state.explanations = {} + if 'project_metrics' not in st.session_state: + st.session_state.project_metrics = {} + +def main(): + load_dotenv() + init_session_state() + setup_page_config() + load_custom_css() + + language, architecture, max_debug_iterations, auto_test, auto_debug = render_sidebar() + + api_key = os.getenv("GEMINI_API_KEY") + if not api_key: + st.error("โš ๏ธ Please set your GEMINI_API_KEY in a .env file to continue") + st.stop() + + if st.session_state.oracle is None: + st.session_state.oracle = CodeOracle(api_key) + st.success("โœ… Singularity-AI Initialized!") + + tab1, tab2, tab3, tab4, tab5, tab6 = render_main_content() + + with tab1: + prompt = render_generate_tab(language, architecture) + if prompt: + with st.spinner("๐Ÿ”ฎ Singularity-AI is crafting your project..."): + project_data = st.session_state.oracle.generate_project(prompt, language, architecture) + if project_data: + st.session_state.current_project = project_data + st.session_state.generation_status = "success" + total_lines = sum(len(content.split('\n')) for content in project_data['files'].values()) + st.session_state.project_metrics = { + 'total_files': len(project_data['files']), + 'total_lines': total_lines, + 'avg_lines_per_file': round(total_lines / len(project_data['files'])) if project_data.get('files') else 0, + 'dependencies': len(project_data.get('dependencies', [])) + } + else: + st.session_state.generation_status = "error" + + render_project_overview(language, architecture) + + with tab2: + action = render_build_test_tab(language, max_debug_iterations) + if action == "build": + with st.spinner("๐Ÿ—๏ธ Building project..."): + temp_dir = tempfile.mkdtemp() + create_project_files(st.session_state.current_project, temp_dir) + build_success = True + build_output = "" + for cmd in st.session_state.current_project.get('build_commands', []): + try: + result = subprocess.run(cmd.split(), cwd=temp_dir, capture_output=True, text=True, timeout=60) + build_output += f"$ {cmd}\n{result.stdout}\n" + if result.returncode != 0: + build_success = False + build_output += f"Error: {result.stderr}\n" + except Exception as e: + build_success = False + build_output += f"Build failed: {str(e)}\n" + st.session_state.build_output = {"success": build_success, "output": build_output} + elif action == "test": + with st.spinner("๐Ÿ”ฌ Running tests..."): + temp_dir = tempfile.mkdtemp() + create_project_files(st.session_state.current_project, temp_dir) + test_results = st.session_state.oracle.run_tests(temp_dir, language, st.session_state.current_project.get('test_commands', [])) + st.session_state.test_results = test_results + elif action == "debug": + with st.spinner("๐Ÿค– Auto-debugging..."): + debug_result = st.session_state.oracle.debug_and_fix(st.session_state.current_project, st.session_state.test_results, max_debug_iterations) + if debug_result["success"]: + st.session_state.current_project = debug_result["updated_project"] + st.success("๐Ÿ”ง Auto-debug completed!") + st.markdown(debug_result["explanation"]) + else: + st.error(f"Auto-debug failed: {debug_result['error']}") + elif action and action.startswith("refactor"): + refactor_type = action.split("_")[1] + with st.spinner(f"๐Ÿ”„ Refactoring for {refactor_type}..."): + result = st.session_state.oracle.refactor_code(st.session_state.current_project, refactor_type) + if result["success"]: + st.session_state.refactor_results[refactor_type] = result["refactored"] + + with tab3: + render_analysis_tab(language) + + with tab4: + render_dashboard_tab() + + with tab5: + action = render_security_tab(language) + if action == "scan": + with st.spinner("๐Ÿ›ก๏ธ Scanning for security vulnerabilities..."): + security_result = st.session_state.oracle.security_scan(st.session_state.current_project, language) + st.session_state.security_report = security_result + + with tab6: + render_deploy_tab(language) + + render_footer() + +if __name__ == "__main__": + main() diff --git a/src/ui.py b/src/ui.py new file mode 100644 index 0000000..edcd795 --- /dev/null +++ b/src/ui.py @@ -0,0 +1,761 @@ +import streamlit as st +import pandas as pd +import plotly.express as px +from datetime import datetime +from src.utils import create_zip_download + +def setup_page_config(): + st.set_page_config( + page_title="Singularity-AI", + page_icon="โ™พ๏ธ", + layout="wide", + initial_sidebar_state="expanded" + ) + +def load_custom_css(): + st.markdown(""" + + """, unsafe_allow_html=True) + +def render_sidebar(): + with st.sidebar: + st.markdown("### โš™๏ธ Configuration") + + # Language selection + language = st.selectbox( + "๐Ÿ’ป Programming Language", + ["Python", "JavaScript", "TypeScript", "Go", "Rust", "Java", "Kotlin", "C++"], + key="language_select" + ) + + # Architecture pattern + architecture = st.selectbox( + "๐Ÿ—๏ธ Architecture Pattern", + ["Standard", "MVC", "Microservices", "Serverless", "Clean Architecture", "Hexagonal"], + key="architecture_select" + ) + + # Advanced settings + st.markdown("### ๐Ÿ”ฌ Advanced Settings") + max_debug_iterations = st.slider("Max Debug Iterations", 1, 10, 3, key="debug_iter") + auto_test = st.checkbox("Auto-run tests", value=True, key="auto_test") + auto_debug = st.checkbox("Auto-debug failures", value=True, key="auto_debug") + + return language, architecture, max_debug_iterations, auto_test, auto_debug + +def render_main_content(): + st.markdown('

โ™พ๏ธ Singularity-AI

', unsafe_allow_html=True) + st.markdown('
Where AI meets infinity โ™พ๏ธ
', unsafe_allow_html=True) + + tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs([ + "๐Ÿš€ Generate", "๐Ÿ”ง Build & Test", "๐Ÿ” Analysis", "๐Ÿ“Š Dashboard", "๐Ÿ›ก๏ธ Security", "๐Ÿš€ Deploy" + ]) + + return tab1, tab2, tab3, tab4, tab5, tab6 + +def render_generate_tab(language, architecture): + with st.expander("๐Ÿš€ Project Generator", expanded=True): + col1, col2 = st.columns([3, 1]) + + with col1: + prompt = st.text_area( + "๐Ÿ“ Describe your project:", + placeholder="Build a REST API for a todo app with user authentication, SQLite database, and CRUD operations", + height=120, + key="project_prompt" + ) + + with col2: + template = st.selectbox( + "โšก Quick Templates", + ["Custom", "Web App + Auth", "REST API", "ML Service", "CLI Tool", "Microservice"], + key="template_select" + ) + + template_prompts = { + "Custom": "", + "Web App + Auth": "Create a modern web application with user authentication, responsive design, and database integration", + "REST API": "Build a RESTful API with CRUD operations, authentication, and comprehensive documentation", + "ML Service": "Create a machine learning inference service with model loading, prediction endpoints, and monitoring", + "CLI Tool": "Build a command-line tool with argument parsing, configuration management, and user-friendly output", + "Microservice": "Create a microservice with health checks, logging, metrics, and containerization" + } + + default_prompt = template_prompts.get(template, "") + + if st.button("๐Ÿง™โ€โ™‚๏ธ Generate Project", type="primary", key="generate_btn"): + if prompt: + return prompt + else: + st.error("โš ๏ธ Please provide a project description") + return None + +def render_project_overview(language, architecture): + if st.session_state.current_project and st.session_state.generation_status == "success": + project = st.session_state.current_project + + st.markdown('
โœจ Project generated successfully!
', unsafe_allow_html=True) + + st.markdown("### ๐Ÿ“‹ Project Overview") + col1, col2 = st.columns(2) + + with col1: + st.markdown(f"**๐Ÿท๏ธ Name:** `{project['project_name']}`") + st.markdown(f"**๐Ÿ’ป Language:** `{language}`") + st.markdown(f"**๐Ÿ“ Files:** `{st.session_state.project_metrics['total_files']}`") + + with col2: + st.markdown(f"**๐Ÿ“ฆ Dependencies:** `{st.session_state.project_metrics['dependencies']}`") + st.markdown(f"**๐Ÿ—๏ธ Architecture:** `{architecture}`") + st.markdown(f"**๐Ÿ“ Lines:** `{st.session_state.project_metrics['total_lines']}`") + + st.markdown(f"**๐Ÿ“ Description:** {project['description']}") + + st.markdown("### ๐Ÿ“ Generated Files") + selected_file = st.selectbox( + "View file:", + list(project['files'].keys()), + key="file_browser" + ) + + if selected_file: + file_ext = selected_file.split('.')[-1] if '.' in selected_file else 'text' + st.code(project['files'][selected_file], language=file_ext) + + zip_data = create_zip_download(project) + st.download_button( + label="๐Ÿ“ฆ Download Project ZIP", + data=zip_data, + file_name=f"{project['project_name']}.zip", + mime="application/zip", + key="download_zip" + ) + +def render_build_test_tab(language, max_debug_iterations): + if not st.session_state.current_project: + st.markdown('
โ„น๏ธ Generate a project first to see build and test options
', unsafe_allow_html=True) + return + + project = st.session_state.current_project + + col1, col2, col3 = st.columns(3) + + with col1: + if st.button("๐Ÿ”จ Build Project", key="build_btn"): + return "build" + + if st.session_state.build_output: + if st.session_state.build_output["success"]: + st.markdown('
โœ… Build successful!
', unsafe_allow_html=True) + else: + st.markdown('
โŒ Build failed
', unsafe_allow_html=True) + + st.code(st.session_state.build_output["output"], language="bash") + + with col2: + if st.button("๐Ÿงช Run Tests", key="test_btn"): + return "test" + + if st.session_state.test_results: + if st.session_state.test_results["success"]: + st.markdown('
โœ… All tests passed!
', unsafe_allow_html=True) + else: + st.markdown('
โŒ Some tests failed
', unsafe_allow_html=True) + + st.code(st.session_state.test_results["output"], language="bash") + + if st.session_state.test_results["errors"]: + st.error("Test Errors:") + st.code(st.session_state.test_results["errors"], language="bash") + + with col3: + if st.button("๐Ÿ”ง Auto-Debug", key="debug_btn"): + if st.session_state.test_results and not st.session_state.test_results["success"]: + return "debug" + else: + st.info("No failing tests to debug") + + st.markdown("### ๐Ÿ”„ Refactoring Options") + refactor_col1, refactor_col2, refactor_col3, refactor_col4 = st.columns(4) + + with refactor_col1: + if st.button("๐Ÿ“š Readability", key="refactor_readability"): + return "refactor_readability" + + if "readability" in st.session_state.refactor_results: + with st.expander("๐Ÿ“š Readability Refactor Result"): + st.markdown(st.session_state.refactor_results["readability"]) + + with refactor_col2: + if st.button("โšก Performance", key="refactor_performance"): + return "refactor_performance" + + if "performance" in st.session_state.refactor_results: + with st.expander("โšก Performance Refactor Result"): + st.markdown(st.session_state.refactor_results["performance"]) + + with refactor_col3: + if st.button("๐Ÿ“ฆ Size", key="refactor_size"): + return "refactor_size" + + if "size" in st.session_state.refactor_results: + with st.expander("๐Ÿ“ฆ Size Refactor Result"): + st.markdown(st.session_state.refactor_results["size"]) + + with refactor_col4: + if st.button("๐Ÿ›ก๏ธ Security", key="refactor_security"): + return "refactor_security" + + if "security" in st.session_state.refactor_results: + with st.expander("๐Ÿ›ก๏ธ Security Refactor Result"): + st.markdown(st.session_state.refactor_results["security"]) + +def render_analysis_tab(language): + if not st.session_state.current_project: + st.markdown('
โ„น๏ธ Generate a project first to see analysis options
', unsafe_allow_html=True) + return + + project = st.session_state.current_project + + st.markdown("### ๐Ÿ“– Explain Code") + explain_file = st.selectbox( + "Select file to explain:", + list(project['files'].keys()), + key="explain_file_select" + ) + + if st.button("๐Ÿ” Explain This File", key="explain_btn"): + with st.spinner("๐Ÿง  Analyzing code..."): + explanation = st.session_state.oracle.explain_code( + project['files'][explain_file], + language + ) + st.session_state.explanations[explain_file] = explanation + + if explain_file in st.session_state.explanations: + with st.expander(f"๐Ÿ“– Explanation: {explain_file}"): + st.markdown(st.session_state.explanations[explain_file]) + + st.markdown("### ๐Ÿ—๏ธ Architecture Overview") + + if st.button("๐Ÿ“Š Visualize Architecture", key="viz_arch_btn"): + files = list(project['files'].keys()) + file_types = {} + + for file in files: + ext = file.split('.')[-1] if '.' in file else 'other' + file_types[ext] = file_types.get(ext, 0) + 1 + + st.session_state.arch_viz_data = file_types + + if hasattr(st.session_state, 'arch_viz_data'): + fig = px.pie( + values=list(st.session_state.arch_viz_data.values()), + names=list(st.session_state.arch_viz_data.keys()), + title="Project File Distribution", + color_discrete_sequence=px.colors.qualitative.Set3 + ) + fig.update_layout( + plot_bgcolor='rgba(0,0,0,0)', + paper_bgcolor='rgba(0,0,0,0)', + font_color='white' + ) + st.plotly_chart(fig, use_container_width=True) + + st.markdown("### ๐Ÿ“ฆ Dependencies") + deps = project.get('dependencies', []) + if deps: + dep_df = pd.DataFrame({'Dependency': deps, 'Type': ['External'] * len(deps)}) + st.dataframe(dep_df, use_container_width=True) + else: + st.info("No external dependencies found") + + st.markdown("### ๐Ÿ“ Code Metrics") + + if hasattr(st.session_state, 'project_metrics') and st.session_state.project_metrics: + metrics = st.session_state.project_metrics + col1, col2, col3, col4 = st.columns(4) + col1.metric("Total Files", metrics['total_files']) + col2.metric("Total Lines", metrics['total_lines']) + col3.metric("Avg Lines/File", metrics['avg_lines_per_file']) + col4.metric("Dependencies", metrics['dependencies']) + elif st.session_state.current_project: + project = st.session_state.current_project + total_files = len(project['files']) + total_lines = sum(len(content.split('\n')) for content in project['files'].values()) + avg_lines = round(total_lines/total_files) if total_files > 0 else 0 + dependencies = len(project.get('dependencies', [])) + + col1, col2, col3, col4 = st.columns(4) + col1.metric("Total Files", total_files) + col2.metric("Total Lines", total_lines) + col3.metric("Avg Lines/File", avg_lines) + col4.metric("Dependencies", dependencies) + +def render_dashboard_tab(): + if not st.session_state.current_project: + st.markdown('
โ„น๏ธ Generate a project first to see the dashboard
', unsafe_allow_html=True) + return + + health_score = 85 + col1, col2, col3 = st.columns(3) + + with col1: + st.metric("๐Ÿฅ Health Score", f"{health_score}%", "5%") + with col2: + test_coverage = "78%" if st.session_state.test_results and st.session_state.test_results["success"] else "0%" + st.metric("๐Ÿงช Test Coverage", test_coverage, "12%") + with col3: + security_rating = "A-" if "security" in st.session_state.refactor_results else "C" + st.metric("๐Ÿ›ก๏ธ Security Rating", security_rating, "0") + + st.markdown("### ๐Ÿ•’ Project Timeline") + timeline_events = [] + if st.session_state.current_project: + timeline_events.append(('Generated', datetime.now().strftime('%H:%M:%S'), 'โœ…')) + if st.session_state.build_output: + status = 'โœ…' if st.session_state.build_output["success"] else 'โŒ' + timeline_events.append(('Built', datetime.now().strftime('%H:%M:%S'), status)) + if st.session_state.test_results: + status = 'โœ…' if st.session_state.test_results["success"] else 'โŒ' + timeline_events.append(('Tested', datetime.now().strftime('%H:%M:%S'), status)) + if st.session_state.security_report: + timeline_events.append(('Secured', datetime.now().strftime('%H:%M:%S'), 'โœ…')) + + if timeline_events: + timeline_data = pd.DataFrame(timeline_events, columns=['Event', 'Timestamp', 'Status']) + st.dataframe(timeline_data, use_container_width=True) + + st.markdown("### ๐Ÿ“ˆ Quality Trends") + + dates = pd.date_range(start='2024-01-01', end='2024-12-31', freq='M') + quality_data = pd.DataFrame({ + 'Date': dates, + 'Code Quality': [75 + i*2 + (i%3)*5 for i in range(len(dates))], + 'Test Coverage': [60 + i*1.5 + (i%2)*3 for i in range(len(dates))], + 'Security Score': [70 + i*1.8 + (i%4)*4 for i in range(len(dates))] + }) + + fig = px.line( + quality_data, + x='Date', + y=['Code Quality', 'Test Coverage', 'Security Score'], + title="Project Health Over Time" + ) + fig.update_layout( + plot_bgcolor='rgba(0,0,0,0)', + paper_bgcolor='rgba(0,0,0,0)', + font_color='white' + ) + st.plotly_chart(fig, use_container_width=True) + +def render_security_tab(language): + if not st.session_state.current_project: + st.markdown('
โ„น๏ธ Generate a project first to run security analysis
', unsafe_allow_html=True) + return + + if st.button("๐Ÿ” Run Security Scan", key="security_scan_btn"): + return "scan" + + if st.session_state.security_report: + if st.session_state.security_report["success"]: + st.markdown("### ๐Ÿ›ก๏ธ Security Report") + st.markdown(st.session_state.security_report["report"]) + else: + st.error(f"Security scan failed: {st.session_state.security_report['error']}") + + st.markdown("### โœ… Security Checklist") + + security_items = [ + "Input validation implemented", + "Authentication mechanisms in place", + "Authorization checks present", + "SQL injection prevention", + "XSS protection enabled", + "CSRF tokens implemented", + "Secure headers configured", + "Dependency vulnerabilities checked" + ] + + for i, item in enumerate(security_items): + st.checkbox(item, value=False, key=f"security_check_{i}") + +def render_deploy_tab(language): + if not st.session_state.current_project: + st.markdown('
โ„น๏ธ Generate a project first to see deployment options
', unsafe_allow_html=True) + return + + project = st.session_state.current_project + + col1, col2 = st.columns(2) + + with col1: + st.markdown("### ๐Ÿ”„ CI/CD Configuration") + cicd_platform = st.selectbox( + "Platform:", + ["GitHub Actions", "GitLab CI", "CircleCI", "Jenkins"], + key="cicd_platform_select" + ) + + if st.button("Generate CI/CD Config", key="generate_cicd_btn"): + with st.spinner("โš™๏ธ Generating CI/CD configuration..."): + cicd_config = st.session_state.oracle.generate_cicd( + project, language, cicd_platform + ) + st.session_state.cicd_configs[cicd_platform] = cicd_config + + if cicd_platform in st.session_state.cicd_configs: + st.code(st.session_state.cicd_configs[cicd_platform], language="yaml") + + st.download_button( + label="๐Ÿ“ฅ Download CI/CD Config", + data=st.session_state.cicd_configs[cicd_platform], + file_name=f"{cicd_platform.lower().replace(' ', '_')}.yml", + mime="text/yaml", + key=f"download_cicd_{cicd_platform}" + ) + + with col2: + st.markdown("### ๐Ÿณ Containerization") + + if st.button("Generate Dockerfile", key="generate_dockerfile_btn"): + dockerfile_prompt = f""" + Generate a production-ready Dockerfile for this {language} project: + + Project: {project['project_name']} + Dependencies: {project.get('dependencies', [])} + Build Commands: {project.get('build_commands', [])} + Run Commands: {project.get('run_commands', [])} + + Include: + - Multi-stage build + - Security best practices + - Optimized layer caching + - Non-root user + - Health checks + """ + + with st.spinner("๐Ÿณ Generating Dockerfile..."): + try: + response = st.session_state.oracle.model.generate_content(dockerfile_prompt) + st.session_state.dockerfile_content = response.text + except Exception as e: + st.error(f"Dockerfile generation failed: {str(e)}") + + if hasattr(st.session_state, 'dockerfile_content'): + st.code(st.session_state.dockerfile_content, language="dockerfile") + + st.download_button( + label="๐Ÿ“ฅ Download Dockerfile", + data=st.session_state.dockerfile_content, + file_name="Dockerfile", + mime="text/plain", + key="download_dockerfile" + ) + + st.markdown("### ๐ŸŒ Deployment Scripts") + + deployment_type = st.selectbox( + "Deployment Target:", + ["Docker Compose", "Kubernetes", "AWS ECS", "Google Cloud Run", "Azure Container Apps"], + key="deployment_type_select" + ) + + if st.button("Generate Deployment Script", key="generate_deploy_btn"): + deploy_prompt = f""" + Generate deployment configuration for {deployment_type} for this project: + + Project: {project['project_name']} + Language: {language} + Dependencies: {project.get('dependencies', [])} + Build Commands: {project.get('build_commands', [])} + Run Commands: {project.get('run_commands', [])} + + Include: + - Service definitions + - Environment variables + - Resource limits + - Health checks + - Networking configuration + - Scaling policies + - Monitoring setup + """ + + with st.spinner(f"๐Ÿš€ Generating {deployment_type} configuration..."): + try: + response = st.session_state.oracle.model.generate_content(deploy_prompt) + if 'deploy_configs' not in st.session_state: + st.session_state.deploy_configs = {} + st.session_state.deploy_configs[deployment_type] = response.text + except Exception as e: + st.error(f"Deployment configuration generation failed: {str(e)}") + + if hasattr(st.session_state, 'deploy_configs') and deployment_type in st.session_state.deploy_configs: + st.code(st.session_state.deploy_configs[deployment_type], language="yaml") + + file_extensions = { + "Docker Compose": "docker-compose.yml", + "Kubernetes": "k8s-deployment.yaml", + "AWS ECS": "ecs-task-definition.json", + "Google Cloud Run": "cloudrun-service.yaml", + "Azure Container Apps": "containerapp.yaml" + } + + filename = file_extensions.get(deployment_type, "deployment.yaml") + + st.download_button( + label=f"๐Ÿ“ฅ Download {deployment_type} Config", + data=st.session_state.deploy_configs[deployment_type], + file_name=filename, + mime="text/yaml", + key=f"download_deploy_{deployment_type}" + ) + + st.markdown("### ๐Ÿ”ง Environment Configuration") + + env_type = st.selectbox( + "Environment Type:", + ["Development", "Staging", "Production"], + key="env_type_select" + ) + + if st.button("Generate Environment Config", key="generate_env_btn"): + env_prompt = f""" + Generate environment configuration for {env_type} environment: + + Project: {project['project_name']} + Language: {language} + + Include appropriate settings for {env_type}: + - Environment variables + - Database configurations + - Logging levels + - Security settings + - Performance optimizations + - Monitoring configurations + """ + + with st.spinner(f"โš™๏ธ Generating {env_type} environment config..."): + try: + response = st.session_state.oracle.model.generate_content(env_prompt) + if 'env_configs' not in st.session_state: + st.session_state.env_configs = {} + st.session_state.env_configs[env_type] = response.text + except Exception as e: + st.error(f"Environment configuration generation failed: {str(e)}") + + if hasattr(st.session_state, 'env_configs') and env_type in st.session_state.env_configs: + st.code(st.session_state.env_configs[env_type], language="bash") + + st.download_button( + label=f"๐Ÿ“ฅ Download {env_type} Config", + data=st.session_state.env_configs[env_type], + file_name=f".env.{env_type.lower()}", + mime="text/plain", + key=f"download_env_{env_type}" + ) + +def render_footer(): + st.markdown("---") + st.markdown( + """ +
+

โ™พ๏ธ Singularity-AI - Where AI meets infinity

+

Autonomous Software Engineering Assistant

+

Powered by Google Gemini โ€ข Built with Streamlit โ€ข Enhanced with infinite possibilities

+
โ™พ๏ธ
+
+ """, + unsafe_allow_html=True + ) diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..4153e3b --- /dev/null +++ b/src/utils.py @@ -0,0 +1,39 @@ +import os +import tempfile +import zipfile +import streamlit as st +from typing import Dict + +def create_project_files(project_data: Dict, base_path: str): + """Create actual files from project data""" + # Ensure base directory exists + os.makedirs(base_path, exist_ok=True) + + for filename, content in project_data["files"].items(): + file_path = os.path.join(base_path, filename) + + # Create directory if filename contains subdirectories + file_dir = os.path.dirname(file_path) + if file_dir and file_dir != base_path: + os.makedirs(file_dir, exist_ok=True) + + try: + with open(file_path, 'w', encoding='utf-8') as f: + f.write(content) + except Exception as e: + st.error(f"Failed to create file {filename}: {str(e)}") + continue + +def create_zip_download(project_data: Dict) -> bytes: + """Create downloadable zip file""" + zip_buffer = tempfile.NamedTemporaryFile(delete=False, suffix='.zip') + + with zipfile.ZipFile(zip_buffer.name, 'w', zipfile.ZIP_DEFLATED) as zip_file: + for filename, content in project_data["files"].items(): + zip_file.writestr(filename, content) + + with open(zip_buffer.name, 'rb') as f: + zip_data = f.read() + + os.unlink(zip_buffer.name) + return zip_data