Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import boto3 | |
| import json | |
| import os | |
| from typing import Optional, Tuple, List | |
| import nbformat | |
| from io import StringIO | |
| import sys | |
| import tempfile | |
| import zipfile | |
| from datetime import datetime | |
| import re | |
| class CodingCopilot: | |
| def __init__(self): | |
| """Initialize the coding copilot with AWS Bedrock client.""" | |
| self.setup_aws_client() | |
| def setup_aws_client(self): | |
| """Setup AWS Bedrock client with credentials from environment variables.""" | |
| try: | |
| self.bedrock_client = boto3.client( | |
| 'bedrock-runtime', | |
| aws_access_key_id=os.getenv('AWS_ACCESS_KEY_ID'), | |
| aws_secret_access_key=os.getenv('AWS_SECRET_ACCESS_KEY'), | |
| region_name='us-east-1' | |
| ) | |
| except Exception as e: | |
| print(f"Error setting up AWS client: {e}") | |
| self.bedrock_client = None | |
| def call_claude(self, prompt: str, max_tokens: int = 8000) -> str: | |
| """Call Claude 3 Haiku via AWS Bedrock with increased token limit.""" | |
| if not self.bedrock_client: | |
| return "β **Error**: AWS Bedrock client not initialized. Please check your credentials." | |
| try: | |
| body = { | |
| "anthropic_version": "bedrock-2023-05-31", | |
| "max_tokens": max_tokens, | |
| "messages": [{"role": "user", "content": prompt}], | |
| "temperature": 0.1, | |
| "top_p": 0.9, | |
| } | |
| response = self.bedrock_client.invoke_model( | |
| modelId="anthropic.claude-3-haiku-20240307-v1:0", | |
| contentType='application/json', | |
| accept='application/json', | |
| body=json.dumps(body) | |
| ) | |
| response_body = json.loads(response['body'].read()) | |
| return response_body['content'][0]['text'] | |
| except Exception as e: | |
| return f"β **Error calling Claude**: {str(e)}" | |
| def read_python_file(self, file_path: str) -> str: | |
| """Read content from a Python file.""" | |
| try: | |
| with open(file_path, 'r', encoding='utf-8') as f: | |
| return f.read() | |
| except Exception as e: | |
| return f"Error reading file: {str(e)}" | |
| def read_notebook_file(self, file_path: str) -> str: | |
| """Read and extract code from a Jupyter notebook file.""" | |
| try: | |
| with open(file_path, 'r', encoding='utf-8') as f: | |
| nb = nbformat.read(f, as_version=4) | |
| code_cells = [] | |
| for cell in nb.cells: | |
| if cell.cell_type == 'code': | |
| code_cells.append(f"# Cell {len(code_cells) + 1}") | |
| code_cells.append(cell.source) | |
| code_cells.append("") | |
| return '\n'.join(code_cells) | |
| except Exception as e: | |
| return f"Error reading notebook: {str(e)}" | |
| def process_files(self, files: List) -> Tuple[str, str]: | |
| """Process uploaded files and return combined content.""" | |
| if not files: | |
| return "", "No files uploaded" | |
| all_content = [] | |
| file_info = [] | |
| for file in files: | |
| file_path = file.name | |
| file_name = os.path.basename(file_path) | |
| file_extension = os.path.splitext(file_path)[1].lower() | |
| if file_extension == '.py': | |
| content = self.read_python_file(file_path) | |
| elif file_extension == '.ipynb': | |
| content = self.read_notebook_file(file_path) | |
| else: | |
| continue | |
| if content and not content.startswith("Error"): | |
| all_content.append(f"# π File: {file_name}") | |
| all_content.append(f"# π Type: {file_extension}") | |
| all_content.append("# " + "="*50) | |
| all_content.append(content) | |
| all_content.append("\n" + "="*60 + "\n") | |
| file_info.append(f"{file_name}") | |
| combined_content = '\n'.join(all_content) | |
| status = f"β Successfully loaded {len(file_info)} files: {', '.join(file_info)}" | |
| return combined_content, status | |
| def extract_code_blocks(self, text: str) -> List[str]: | |
| """Extract code blocks from response text.""" | |
| code_blocks = re.findall(r'```(?:\w+)?\n(.*?)\n```', text, re.DOTALL) | |
| return code_blocks | |
| def create_download_file(self, content: str, filename: str = "generated_code.py") -> str: | |
| """Create a downloadable file with the given content.""" | |
| timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
| base_name = os.path.splitext(filename)[0] | |
| extension = os.path.splitext(filename)[1] or '.py' | |
| filename = f"{base_name}_{timestamp}{extension}" | |
| temp_file = tempfile.NamedTemporaryFile(mode='w', suffix=extension, delete=False) | |
| temp_file.write(content) | |
| temp_file.close() | |
| return temp_file.name | |
| def process_message(self, message: str, files: List = None, history: List = None) -> Tuple[str, Optional[str]]: | |
| """Process user message and return response with optional download file.""" | |
| if history is None: | |
| history = [] | |
| # Process files if provided | |
| file_content = "" | |
| file_status = "" | |
| if files: | |
| file_content, file_status = self.process_files(files) | |
| # Detect continuation requests | |
| continue_keywords = ['continue', 'continue the code', 'continue from where', 'keep going', 'add more', 'extend', 'complete the'] | |
| is_continuation = any(keyword in message.lower() for keyword in continue_keywords) | |
| # Build comprehensive context from history | |
| context = "" | |
| if history: | |
| if is_continuation: | |
| context = "\n\nFull conversation context for continuation:\n" | |
| for i, (user_msg, assistant_msg) in enumerate(history[-5:]): | |
| context += f"Exchange {i+1}:\nUser: {user_msg}\nAssistant: {assistant_msg}\n\n" | |
| else: | |
| context = "\n\nRecent conversation context:\n" | |
| for i, (user_msg, assistant_msg) in enumerate(history[-3:]): | |
| context += f"User: {user_msg}\nAssistant: {assistant_msg}\n\n" | |
| # Build specialized prompts based on request type | |
| if is_continuation: | |
| continuation_instructions = """CRITICAL INSTRUCTIONS FOR CONTINUATION: | |
| 1. Look at the previous conversation to understand what code was generated | |
| 2. Continue from where the previous code left off - DO NOT start from the beginning | |
| 3. Maintain the same coding style, structure, and patterns | |
| 4. Add new functionality or complete incomplete sections | |
| 5. Generate substantial code (aim for 500-2000+ lines if needed) | |
| 6. Ensure the continuation integrates seamlessly with previous code""" | |
| file_content_section = f"\nCode files content for reference:\n```\n{file_content}\n```" if file_content else "" | |
| final_instruction = "Based on the previous conversation, continue the code generation. Do NOT restart - pick up exactly where the previous response left off and continue building upon it. Provide substantial, complete code sections." | |
| prompt = f"""You are an advanced coding assistant. The user is asking you to CONTINUE or EXTEND previous code. | |
| {continuation_instructions} | |
| User's continuation request: {message} | |
| {file_status} | |
| {file_content_section} | |
| {context} | |
| {final_instruction}""" | |
| else: | |
| generation_keywords = ['create', 'generate', 'build', 'make', 'develop', 'write code', 'implement', 'design'] | |
| is_generation = any(keyword in message.lower() for keyword in generation_keywords) | |
| if is_generation: | |
| generation_instructions = """CRITICAL INSTRUCTIONS FOR CODE GENERATION: | |
| 1. Generate COMPLETE, COMPREHENSIVE code - aim for 500-3000+ lines when appropriate | |
| 2. Include ALL necessary components: classes, functions, error handling, documentation | |
| 3. Create fully functional, production-ready applications | |
| 4. Add comprehensive comments and docstrings | |
| 5. Include proper imports, dependencies, and structure | |
| 6. Don't truncate or abbreviate - provide the FULL implementation | |
| 7. If the project is large, focus on core functionality but make it complete""" | |
| file_content_section = f"\nReference code files:\n```\n{file_content}\n```" if file_content else "" | |
| final_instruction = "Generate comprehensive, complete code that fully implements the requested functionality. Provide extensive code with proper structure, documentation, and all necessary components." | |
| prompt = f"""You are an advanced coding assistant specialized in generating comprehensive, production-ready code. | |
| {generation_instructions} | |
| User's request: {message} | |
| {file_status} | |
| {file_content_section} | |
| {context} | |
| {final_instruction}""" | |
| else: | |
| file_content_section = f"\nCode files content:\n```\n{file_content}\n```" if file_content else "" | |
| prompt = f"""You are an advanced coding assistant. Provide detailed, comprehensive responses. | |
| User's request: {message} | |
| {file_status} | |
| {file_content_section} | |
| {context} | |
| Provide a thorough and helpful response. If suggesting code changes, provide complete implementations.""" | |
| # Get response from Claude | |
| response = self.call_claude(prompt, max_tokens=8000) | |
| # Extract code blocks for download | |
| code_blocks = self.extract_code_blocks(response) | |
| download_file = None | |
| if code_blocks: | |
| combined_code = "\n\n".join(code_blocks) | |
| if len(combined_code.strip()) > 50: # Only create download if substantial code | |
| download_file = self.create_download_file(combined_code) | |
| return response, download_file | |
| # Initialize the copilot | |
| copilot = CodingCopilot() | |
| # FIXED CSS - Proper layout and visible input area | |
| fixed_css = """ | |
| /* Reset and base styles */ | |
| * { | |
| box-sizing: border-box !important; | |
| } | |
| .gradio-container { | |
| max-width: none !important; | |
| width: 100% !important; | |
| background: #0a0a0a !important; | |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif !important; | |
| color: #ffffff !important; | |
| padding: 1rem !important; | |
| min-height: 100vh !important; | |
| } | |
| /* Header */ | |
| .header-container { | |
| background: linear-gradient(135deg, #1a1a1a 0%, #2d1b1b 50%, #1a1a1a 100%) !important; | |
| border: 1px solid #dc2626 !important; | |
| border-radius: 16px !important; | |
| padding: 1.5rem !important; | |
| margin-bottom: 1rem !important; | |
| box-shadow: 0 8px 32px rgba(220, 38, 38, 0.15) !important; | |
| text-align: center !important; | |
| } | |
| .header-title { | |
| color: #ffffff !important; | |
| font-size: 2.2rem !important; | |
| font-weight: 700 !important; | |
| margin: 0 !important; | |
| background: linear-gradient(135deg, #ffffff 0%, #dc2626 100%) !important; | |
| -webkit-background-clip: text !important; | |
| -webkit-text-fill-color: transparent !important; | |
| background-clip: text !important; | |
| } | |
| .header-subtitle { | |
| color: #a1a1aa !important; | |
| font-size: 1rem !important; | |
| margin: 0.5rem 0 0 0 !important; | |
| font-weight: 400 !important; | |
| } | |
| /* Main layout */ | |
| .main-layout { | |
| display: flex !important; | |
| flex-direction: row !important; | |
| gap: 1.5rem !important; | |
| width: 100% !important; | |
| min-height: calc(100vh - 200px) !important; | |
| } | |
| /* Sidebar */ | |
| .sidebar { | |
| background: linear-gradient(180deg, #1a1a1a 0%, #0f0f0f 100%) !important; | |
| border: 1px solid #dc2626 !important; | |
| border-radius: 16px !important; | |
| padding: 1.5rem !important; | |
| width: 320px !important; | |
| min-width: 320px !important; | |
| max-width: 320px !important; | |
| box-shadow: 0 8px 32px rgba(220, 38, 38, 0.1) !important; | |
| overflow-y: auto !important; | |
| height: fit-content !important; | |
| max-height: calc(100vh - 200px) !important; | |
| } | |
| /* Chat area */ | |
| .chat-area { | |
| background: linear-gradient(180deg, #111111 0%, #0a0a0a 100%) !important; | |
| border: 1px solid #262626 !important; | |
| border-radius: 16px !important; | |
| flex: 1 !important; | |
| display: flex !important; | |
| flex-direction: column !important; | |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important; | |
| min-height: 600px !important; | |
| } | |
| /* Chat content area */ | |
| .chat-content { | |
| flex: 1 !important; | |
| padding: 1.5rem !important; | |
| overflow-y: auto !important; | |
| min-height: 400px !important; | |
| max-height: 500px !important; | |
| } | |
| /* Input section - FIXED to be visible */ | |
| .input-section { | |
| background: #1a1a1a !important; | |
| border-top: 1px solid #262626 !important; | |
| padding: 1.5rem !important; | |
| border-radius: 0 0 16px 16px !important; | |
| min-height: 300px !important; | |
| } | |
| /* Quick Actions */ | |
| .quick-actions { | |
| margin-bottom: 2rem !important; | |
| padding-bottom: 1.5rem !important; | |
| border-bottom: 1px solid #dc2626 !important; | |
| } | |
| .sidebar-title { | |
| color: #dc2626 !important; | |
| font-weight: 700 !important; | |
| font-size: 1.1rem !important; | |
| margin-bottom: 1rem !important; | |
| text-transform: uppercase !important; | |
| letter-spacing: 0.5px !important; | |
| display: flex !important; | |
| align-items: center !important; | |
| gap: 0.5rem !important; | |
| } | |
| .quick-btn { | |
| background: #1a1a1a !important; | |
| color: #dc2626 !important; | |
| border: 1px solid #dc2626 !important; | |
| border-radius: 8px !important; | |
| padding: 0.8rem 1rem !important; | |
| font-weight: 500 !important; | |
| cursor: pointer !important; | |
| transition: all 0.3s ease !important; | |
| margin-bottom: 0.6rem !important; | |
| width: 100% !important; | |
| text-align: left !important; | |
| font-size: 0.85rem !important; | |
| display: flex !important; | |
| align-items: center !important; | |
| gap: 0.6rem !important; | |
| } | |
| .quick-btn:hover { | |
| background: #dc2626 !important; | |
| color: #ffffff !important; | |
| transform: translateX(3px) !important; | |
| box-shadow: 0 4px 12px rgba(220, 38, 38, 0.2) !important; | |
| } | |
| /* Capabilities */ | |
| .capabilities { | |
| color: #d1d5db !important; | |
| font-size: 0.85rem !important; | |
| line-height: 1.5 !important; | |
| } | |
| .capabilities strong { | |
| color: #ffffff !important; | |
| display: block !important; | |
| margin-bottom: 0.3rem !important; | |
| } | |
| .capability-item { | |
| margin-bottom: 1rem !important; | |
| padding: 0.5rem 0 !important; | |
| border-bottom: 1px solid #262626 !important; | |
| } | |
| .capability-item:last-child { | |
| border-bottom: none !important; | |
| } | |
| /* Download section */ | |
| .download-section { | |
| background: #1a1a1a !important; | |
| border: 1px solid #dc2626 !important; | |
| border-radius: 8px !important; | |
| padding: 1rem !important; | |
| margin-bottom: 1rem !important; | |
| } | |
| /* File upload */ | |
| .file-upload { | |
| background: #1a1a1a !important; | |
| border: 1px dashed #404040 !important; | |
| border-radius: 8px !important; | |
| padding: 1rem !important; | |
| margin-bottom: 1rem !important; | |
| transition: all 0.3s ease !important; | |
| } | |
| .file-upload:hover { | |
| border-color: #dc2626 !important; | |
| background: #262626 !important; | |
| } | |
| /* Message input */ | |
| .msg-input { | |
| background: #262626 !important; | |
| border: 1px solid #404040 !important; | |
| border-radius: 8px !important; | |
| color: #ffffff !important; | |
| padding: 1rem !important; | |
| font-size: 0.95rem !important; | |
| line-height: 1.4 !important; | |
| resize: vertical !important; | |
| transition: all 0.3s ease !important; | |
| width: 100% !important; | |
| margin-bottom: 1rem !important; | |
| min-height: 100px !important; | |
| } | |
| .msg-input:focus { | |
| outline: none !important; | |
| border-color: #dc2626 !important; | |
| box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.1) !important; | |
| } | |
| .msg-input::placeholder { | |
| color: #6b7280 !important; | |
| } | |
| /* Button row */ | |
| .btn-row { | |
| display: flex !important; | |
| gap: 1rem !important; | |
| align-items: center !important; | |
| justify-content: flex-end !important; | |
| } | |
| .btn-primary { | |
| background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%) !important; | |
| color: white !important; | |
| border: none !important; | |
| border-radius: 8px !important; | |
| padding: 0.8rem 1.5rem !important; | |
| font-weight: 600 !important; | |
| font-size: 0.9rem !important; | |
| cursor: pointer !important; | |
| transition: all 0.3s ease !important; | |
| box-shadow: 0 4px 16px rgba(220, 38, 38, 0.2) !important; | |
| text-transform: uppercase !important; | |
| letter-spacing: 0.5px !important; | |
| min-width: 80px !important; | |
| } | |
| .btn-primary:hover { | |
| background: linear-gradient(135deg, #b91c1c 0%, #991b1b 100%) !important; | |
| transform: translateY(-1px) !important; | |
| box-shadow: 0 6px 20px rgba(220, 38, 38, 0.3) !important; | |
| } | |
| .btn-secondary { | |
| background: #262626 !important; | |
| color: #ffffff !important; | |
| border: 1px solid #404040 !important; | |
| border-radius: 8px !important; | |
| padding: 0.8rem 1.5rem !important; | |
| font-weight: 500 !important; | |
| cursor: pointer !important; | |
| transition: all 0.3s ease !important; | |
| text-transform: uppercase !important; | |
| letter-spacing: 0.5px !important; | |
| font-size: 0.9rem !important; | |
| min-width: 80px !important; | |
| } | |
| .btn-secondary:hover { | |
| background: #404040 !important; | |
| border-color: #dc2626 !important; | |
| } | |
| /* Chatbot container */ | |
| .chatbot-container { | |
| border: none !important; | |
| background: transparent !important; | |
| overflow-y: auto !important; | |
| scroll-behavior: smooth !important; | |
| } | |
| /* Footer */ | |
| .footer { | |
| background: #0a0a0a !important; | |
| border-top: 1px solid #262626 !important; | |
| padding: 1rem !important; | |
| text-align: center !important; | |
| color: #6b7280 !important; | |
| border-radius: 8px !important; | |
| font-size: 0.8rem !important; | |
| margin-top: 2rem !important; | |
| } | |
| .footer strong { | |
| color: #dc2626 !important; | |
| } | |
| /* Scrollbar */ | |
| ::-webkit-scrollbar { | |
| width: 6px !important; | |
| height: 6px !important; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #1a1a1a !important; | |
| border-radius: 3px !important; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #404040 !important; | |
| border-radius: 3px !important; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #dc2626 !important; | |
| } | |
| /* Code blocks */ | |
| pre { | |
| background: #1a1a1a !important; | |
| border: 1px solid #404040 !important; | |
| border-radius: 6px !important; | |
| padding: 1rem !important; | |
| overflow-x: auto !important; | |
| font-size: 0.85rem !important; | |
| } | |
| code { | |
| background: #262626 !important; | |
| padding: 2px 4px !important; | |
| border-radius: 3px !important; | |
| font-size: 0.85rem !important; | |
| } | |
| /* Responsive design */ | |
| @media (max-width: 768px) { | |
| .main-layout { | |
| flex-direction: column !important; | |
| } | |
| .sidebar { | |
| width: 100% !important; | |
| max-width: none !important; | |
| min-width: auto !important; | |
| height: auto !important; | |
| max-height: 400px !important; | |
| } | |
| .header-title { | |
| font-size: 1.8rem !important; | |
| } | |
| } | |
| """ | |
| def process_chat_message(message, files, history): | |
| """Process a new chat message with download support.""" | |
| if not message.strip() and not files: | |
| return history, history, "", None, "" | |
| if history is None: | |
| history = [] | |
| user_msg = message | |
| if files: | |
| file_names = [os.path.basename(f.name) for f in files] | |
| user_msg += f" π *[Files: {', '.join(file_names)}]*" | |
| # Get AI response with potential download file | |
| ai_response, download_file = copilot.process_message(message, files, history) | |
| # Add to history | |
| history.append([user_msg, ai_response]) | |
| # Return download file info | |
| download_info = "" | |
| if download_file: | |
| download_info = "π **Code generated successfully!** Click the download button below to save your code." | |
| return history, history, "", download_file, download_info | |
| def clear_chat(): | |
| """Clear the chat history.""" | |
| return [], [], None, "" | |
| def update_download_file(response, history): | |
| """Update download file when new response is generated.""" | |
| if not response: | |
| return None, "" | |
| # Extract code blocks from the latest response | |
| code_blocks = copilot.extract_code_blocks(response) | |
| if code_blocks: | |
| combined_code = "\n\n".join(code_blocks) | |
| if len(combined_code.strip()) > 50: | |
| download_file = copilot.create_download_file(combined_code) | |
| return download_file, "π **Code generated!** Download available below." | |
| return None, "" | |
| # Create the main interface | |
| with gr.Blocks(css=fixed_css, title="Coding Copilot Pro", theme=gr.themes.Base()) as app: | |
| # Header | |
| gr.HTML(""" | |
| <div class="header-container"> | |
| <h1 class="header-title">π CODING COPILOT PRO</h1> | |
| <p class="header-subtitle">Advanced AI-Powered Development Assistant β’ Powered by Claude 3 Haiku</p> | |
| </div> | |
| """) | |
| # Main content container | |
| with gr.Row(elem_classes=["main-layout"]): | |
| # Left Sidebar | |
| with gr.Column(elem_classes=["sidebar"], scale=0): | |
| # Quick Actions Section | |
| with gr.Column(elem_classes=["quick-actions"]): | |
| gr.HTML('<h3 class="sidebar-title"><span>β‘</span>QUICK ACTIONS</h3>') | |
| quick_generate = gr.Button("π₯ Generate Code", elem_classes=["quick-btn"]) | |
| quick_review = gr.Button("π Code Review", elem_classes=["quick-btn"]) | |
| quick_debug = gr.Button("π Debug & Fix", elem_classes=["quick-btn"]) | |
| quick_optimize = gr.Button("β‘ Optimize Code", elem_classes=["quick-btn"]) | |
| quick_explain = gr.Button("π Explain Code", elem_classes=["quick-btn"]) | |
| quick_test = gr.Button("π§ͺ Create Tests", elem_classes=["quick-btn"]) | |
| # Capabilities Section | |
| with gr.Column(): | |
| gr.HTML('<h3 class="sidebar-title"><span>π―</span>CAPABILITIES</h3>') | |
| gr.HTML(""" | |
| <div class="capabilities"> | |
| <div class="capability-item"> | |
| <strong>π» Code Generation</strong> | |
| Complete applications, modules, algorithms & APIs | |
| </div> | |
| <div class="capability-item"> | |
| <strong>π Code Analysis</strong> | |
| Reviews, optimization, security & architecture | |
| </div> | |
| <div class="capability-item"> | |
| <strong>π Debug & Test</strong> | |
| Error fixes, unit tests & refactoring | |
| </div> | |
| <div class="capability-item"> | |
| <strong>π Documentation</strong> | |
| Docstrings, API docs & explanations | |
| </div> | |
| </div> | |
| """) | |
| # Right Chat Container | |
| with gr.Column(elem_classes=["chat-area"], scale=1): | |
| # Chat Messages Area | |
| with gr.Column(elem_classes=["chat-content"]): | |
| chatbot = gr.Chatbot( | |
| height=400, | |
| show_label=False, | |
| container=True, | |
| avatar_images=("π¨βπ»", "π€"), | |
| elem_classes=["chatbot-container"] | |
| ) | |
| # Input Section - COMPLETELY VISIBLE NOW | |
| with gr.Column(elem_classes=["input-section"]): | |
| # Download section - Show status and file | |
| with gr.Row(): | |
| download_status = gr.HTML("", elem_classes=["download-section"]) | |
| with gr.Row(): | |
| download_file = gr.File( | |
| label="π₯ Download Generated Code", | |
| visible=True, | |
| interactive=False, | |
| elem_classes=["download-section"] | |
| ) | |
| # File upload | |
| files = gr.File( | |
| label="π Upload Code Files (.py, .ipynb)", | |
| file_count="multiple", | |
| file_types=[".py", ".ipynb"], | |
| elem_classes=["file-upload"] | |
| ) | |
| # Message input | |
| msg = gr.Textbox( | |
| label="Your Message", | |
| placeholder="Describe what you want to build, analyze, or improve... Type 'continue' to extend previous code.", | |
| show_label=True, | |
| lines=4, | |
| max_lines=8, | |
| elem_classes=["msg-input"] | |
| ) | |
| # Button row | |
| with gr.Row(elem_classes=["btn-row"]): | |
| clear = gr.Button( | |
| "CLEAR", | |
| variant="secondary", | |
| elem_classes=["btn-secondary"] | |
| ) | |
| submit = gr.Button( | |
| "SEND", | |
| variant="primary", | |
| elem_classes=["btn-primary"] | |
| ) | |
| # Hidden state | |
| chat_history = gr.State([]) | |
| # Event handlers | |
| def handle_submit(message, files, history): | |
| result = process_chat_message(message, files, history) | |
| return result | |
| # Quick action button handlers | |
| quick_generate.click( | |
| lambda: "Please generate a complete, production-ready application based on the requirements. Include all necessary components, error handling, documentation, and best practices.", | |
| outputs=msg | |
| ) | |
| quick_review.click( | |
| lambda: "Please perform a comprehensive code review of the uploaded files. Analyze code quality, identify potential bugs, suggest performance improvements, check for security vulnerabilities, and provide detailed recommendations with examples.", | |
| outputs=msg | |
| ) | |
| quick_debug.click( | |
| lambda: "Please debug the uploaded code thoroughly. Identify any errors, bugs, logical issues, or potential runtime problems. Provide detailed explanations and complete fixed versions of the code.", | |
| outputs=msg | |
| ) | |
| quick_optimize.click( | |
| lambda: "Please optimize the uploaded code for better performance, memory usage, and readability. Provide the complete optimized version with explanations of the improvements made.", | |
| outputs=msg | |
| ) | |
| quick_explain.click( | |
| lambda: "Please provide a detailed explanation of the uploaded code. Break down its functionality, explain the algorithms used, document all functions and classes, and create comprehensive documentation.", | |
| outputs=msg | |
| ) | |
| quick_test.click( | |
| lambda: "Please create comprehensive unit tests for the uploaded code. Include test cases for all functions, edge cases, error handling, and integration tests where applicable.", | |
| outputs=msg | |
| ) | |
| # Main chat functionality | |
| submit.click( | |
| handle_submit, | |
| inputs=[msg, files, chat_history], | |
| outputs=[chatbot, chat_history, msg, download_file, download_status] | |
| ).then( | |
| lambda: None, # Clear files after processing | |
| outputs=files | |
| ) | |
| msg.submit( | |
| handle_submit, | |
| inputs=[msg, files, chat_history], | |
| outputs=[chatbot, chat_history, msg, download_file, download_status] | |
| ).then( | |
| lambda: None, # Clear files after processing | |
| outputs=files | |
| ) | |
| clear.click( | |
| clear_chat, | |
| outputs=[chatbot, chat_history, download_file, download_status] | |
| ) | |
| # Footer - Completing from where it ended | |
| gr.HTML(""" | |
| <div class="footer"> | |
| <p><strong>π CODING COPILOT PRO</strong> - Advanced AI Development Assistant</p> | |
| <p>Powered by <strong>Claude 3 Haiku</strong> via AWS Bedrock β’ Built with Gradio</p> | |
| <p>π‘ Upload your code files and describe what you want to build, analyze, or improve!</p> | |
| </div> | |
| """) | |
| # Show download file when available | |
| def update_download_visibility(file_path, status): | |
| return file_path, status | |
| # Update download file visibility when status changes | |
| download_status.change( | |
| update_download_visibility, | |
| inputs=[download_file, download_status], | |
| outputs=[download_file, download_status] | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| print("π Starting Coding Copilot Pro...") | |
| print("π Features:") | |
| print(" β’ Complete code generation with continuation support") | |
| print(" β’ File upload support for .py and .ipynb files") | |
| print(" β’ Comprehensive code analysis and debugging") | |
| print(" β’ Download generated code as files") | |
| print(" β’ Quick action buttons for common tasks") | |
| print(" β’ Dark theme with responsive design") | |
| print() | |
| print("π§ Requirements:") | |
| print(" β’ Set AWS_ACCESS_KEY_ID environment variable") | |
| print(" β’ Set AWS_SECRET_ACCESS_KEY environment variable") | |
| print(" β’ Ensure AWS Bedrock access to Claude 3 Haiku") | |
| print() | |
| # Launch with optimized settings | |
| app.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False, | |
| debug=False, | |
| show_error=True, | |
| quiet=False, | |
| inbrowser=True, | |
| height=800, | |
| favicon_path=None, | |
| ssl_verify=False, | |
| app_kwargs={ | |
| "docs_url": None, | |
| "redoc_url": None, | |
| } | |
| ) |