File size: 35,803 Bytes
2b166d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
import gradio as gr
from agno.agent import Agent
from agno.models.google import Gemini
from typing import Optional, Dict, Any
import tempfile
import os
import ast
import contextlib
import io
import sys
from PIL import Image
import subprocess
import json

class MultiLanguageExecutor:
    """A safer alternative to sandbox execution with support for multiple languages"""
    
    def __init__(self, timeout=10):
        self.timeout = timeout
        self.allowed_modules = [
            'math', 'datetime', 'collections', 'itertools', 
            'functools', 'heapq', 'bisect', 'array', 'string'
        ]
        
        # Language configurations
        self.language_configs = {
            'python': {
                'extension': '.py',
                'run_command': lambda file: f'python "{file}"',
                'comment_syntax': '#',
                'sample_template': '''def main():

    # Your code here

    pass



if __name__ == "__main__":

    main()'''
            },
            'javascript': {
                'extension': '.js',
                'run_command': lambda file: f'node "{file}"',
                'comment_syntax': '//',
                'sample_template': '''function main() {

    // Your code here

}



main();'''
            },
            'typescript': {
                'extension': '.ts',
                'run_command': lambda file: f'npx ts-node "{file}"',
                'comment_syntax': '//',
                'sample_template': '''function main(): void {

    // Your code here

}



main();'''
            },
            'html': {
                'extension': '.html',
                'run_command': None,  # HTML doesn't execute, just validate
                'comment_syntax': '<!--',
                'sample_template': '''<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Document</title>

</head>

<body>

    <!-- Your content here -->

</body>

</html>'''
            },
            'css': {
                'extension': '.css',
                'run_command': None,  # CSS doesn't execute, just validate
                'comment_syntax': '/*',
                'sample_template': '''/* Your CSS styles here */

body {

    font-family: Arial, sans-serif;

    margin: 0;

    padding: 0;

}'''
            },
            'tsx': {
                'extension': '.tsx',
                'run_command': lambda file: f'npx ts-node "{file}"',
                'comment_syntax': '//',
                'sample_template': '''import React from 'react';



const Component: React.FC = () => {

    return (

        <div>

            {/* Your JSX here */}

        </div>

    );

};



export default Component;'''
            },
            'java': {
                'extension': '.java',
                'run_command': lambda file: f'javac "{file}" && java "{os.path.splitext(os.path.basename(file))[0]}"',
                'comment_syntax': '//',
                'sample_template': '''public class Main {

    public static void main(String[] args) {

        // Your code here

    }

}'''
            },
            'c': {
                'extension': '.c',
                'run_command': lambda file: f'gcc "{file}" -o "{os.path.splitext(file)[0]}" && "{os.path.splitext(file)[0]}"',
                'comment_syntax': '//',
                'sample_template': '''#include <stdio.h>



int main() {

    // Your code here

    return 0;

}'''
            },
            'cpp': {
                'extension': '.cpp',
                'run_command': lambda file: f'g++ "{file}" -o "{os.path.splitext(file)[0]}" && "{os.path.splitext(file)[0]}"',
                'comment_syntax': '//',
                'sample_template': '''#include <iostream>

using namespace std;



int main() {

    // Your code here

    return 0;

}'''
            }
        }
    
    def run_code(self, code: str, language: str = 'python') -> Dict[str, Any]:
        """Execute code in the specified language with restrictions"""
        result = {
            "success": False,
            "output": "",
            "error": "",
            "logs": "",
            "language": language
        }
        
        if language not in self.language_configs:
            result["error"] = f"Unsupported language: {language}"
            return result
        
        config = self.language_configs[language]
        
        # For markup languages (HTML, CSS), just validate syntax
        if language in ['html', 'css']:
            return self._validate_markup(code, language)
        
        # For other languages, attempt execution
        return self._execute_code(code, config, result)
    
    def _validate_markup(self, code: str, language: str) -> Dict[str, Any]:
        """Validate HTML/CSS syntax"""
        result = {
            "success": True,
            "output": f"βœ… {language.upper()} code appears to be well-formed.",
            "error": "",
            "logs": "",
            "language": language
        }
        
        # Basic validation
        if language == 'html':
            if not code.strip().startswith('<!DOCTYPE') and not code.strip().startswith('<html'):
                result["logs"] = "Note: Consider adding DOCTYPE and html tags for complete HTML structure."
        elif language == 'css':
            if '{' in code and '}' not in code:
                result["error"] = "CSS syntax error: Missing closing brace '}'"
                result["success"] = False
        
        return result
    
    def _execute_code(self, code: str, config: Dict, result: Dict) -> Dict[str, Any]:
        """Execute code for compilable/interpretable languages"""
        try:
            # Create temporary file
            with tempfile.NamedTemporaryFile(
                mode='w', 
                suffix=config['extension'], 
                delete=False, 
                encoding='utf-8'
            ) as tmp_file:
                tmp_file.write(code)
                tmp_file_path = tmp_file.name
            
            # Special handling for Python (use the safer execution)
            if result["language"] == 'python':
                return self._run_python_safe(code)
            
            # For other languages, use subprocess with timeout
            if config['run_command']:
                cmd = config['run_command'](tmp_file_path)
                process = subprocess.run(
                    cmd,
                    shell=True,
                    capture_output=True,
                    text=True,
                    timeout=self.timeout,
                    cwd=os.path.dirname(tmp_file_path)
                )
                
                result["output"] = process.stdout
                result["error"] = process.stderr
                result["success"] = process.returncode == 0
                
                if not result["success"] and not result["error"]:
                    result["error"] = f"Process exited with code {process.returncode}"
            
        except subprocess.TimeoutExpired:
            result["error"] = f"Execution timed out after {self.timeout} seconds"
        except FileNotFoundError as e:
            result["error"] = f"Required compiler/interpreter not found: {str(e)}"
        except Exception as e:
            result["error"] = f"Execution error: {str(e)}"
        finally:
            # Clean up temporary file
            try:
                if 'tmp_file_path' in locals() and os.path.exists(tmp_file_path):
                    os.remove(tmp_file_path)
                    # Also remove compiled files for C/C++/Java
                    base_name = os.path.splitext(tmp_file_path)[0]
                    for ext in ['.exe', '.class', '']:
                        compiled_file = base_name + ext
                        if os.path.exists(compiled_file):
                            os.remove(compiled_file)
            except:
                pass
        
        return result
    
    def _run_python_safe(self, code: str) -> Dict[str, Any]:
        """Execute Python code safely with restrictions (same as original SafeCodeExecutor)"""
        stdout_capture = io.StringIO()
        stderr_capture = io.StringIO()
        
        result = {
            "success": False,
            "output": "",
            "error": "",
            "logs": "",
            "language": "python"
        }
        
        try:
            # Parse and validate the code
            parsed = ast.parse(code)
            
            # Check for disallowed constructs
            for node in ast.walk(parsed):
                if isinstance(node, (ast.Import, ast.ImportFrom)):
                    for alias in node.names:
                        module_name = alias.name if isinstance(node, ast.Import) else node.module
                        if module_name and not any(module_name == allowed or module_name.startswith(allowed + '.') 
                                                 for allowed in self.allowed_modules):
                            result["error"] = f"Import of module '{module_name}' is not allowed"
                            return result
                
                # Disable dangerous functions/constructs
                if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
                    if node.func.id in ['eval', 'exec', 'open', 'exit', 'quit', 'compile']:
                        result["error"] = f"Use of '{node.func.id}' function is not allowed"
                        return result
            
            # Execute the code with restrictions
            with contextlib.redirect_stdout(stdout_capture), contextlib.redirect_stderr(stderr_capture):
                locals_dict = {}
                exec(code, {"__builtins__": self._get_safe_builtins()}, locals_dict)
                
                # Check if there's a main function or similar output
                output = stdout_capture.getvalue()
                if not output and "main" in locals_dict and callable(locals_dict["main"]):
                    output = str(locals_dict["main"]())
                
                result["success"] = True
                result["output"] = output
                
        except Exception as e:
            result["error"] = f"Execution error: {str(e)}"
        
        result["logs"] = stderr_capture.getvalue()
        return result
    
    def _get_safe_builtins(self):
        """Create a safe subset of builtins"""
        safe_builtins = {
            'None': None,
            'True': True,
            'False': False,
            'bool': bool,
            'int': int,
            'float': float,
            'str': str,
            'list': list,
            'tuple': tuple,
            'dict': dict,
            'set': set,
            'len': len,
            'range': range,
            'sum': sum,
            'min': min,
            'max': max,
            'abs': abs,
            'round': round,
            'zip': zip,
            'enumerate': enumerate,
            'isinstance': isinstance,
            'issubclass': issubclass,
            'hasattr': hasattr,
            'getattr': getattr,
            'setattr': setattr,
        }
        return safe_builtins

class MultimodalCodingAgent:
    def __init__(self, gemini_api_key: str):
        self.gemini_api_key = gemini_api_key
        self.executor = MultiLanguageExecutor()
        
        # Create a single agent for all tasks
        self.agent = Agent(
            model=Gemini(id="gemini-2.0-flash", api_key=gemini_api_key),
            markdown=True
        )
        
        # Store system prompt for use in individual requests
        self.system_prompt = """You are a multimodal coding assistant. Your capabilities include:

        1. Analyzing images containing code or problem statements

        2. Generating code solutions for coding problems in multiple programming languages

        3. Explaining and debugging code execution results

        

        Follow these guidelines:

        - For image analysis, extract and describe any code or problem statements clearly

        - For code generation, write clean, efficient code with proper documentation in the requested language

        - For execution results, provide clear explanations of outputs or errors

        - Always prioritize security and avoid suggesting dangerous code constructs

        - Generate code in the exact format and language requested by the user

        - Match the user's requirements precisely without deviation"""
    
    def process_image(self, image: Image.Image, language: str = 'python') -> str:
        """Process an image containing code or problem statement"""
        prompt = f"""{self.system_prompt}



        Analyze this image and extract any coding problem or code snippet shown. 

        Be very specific about what you see in the image. If you see actual code, transcribe it exactly.

        Describe it in clear natural language, including any:

        1. Problem statement or code functionality

        2. Variable assignments and function definitions

        3. Logic flow and conditions

        4. Expected behavior or output

        Format it as a proper coding problem description for {language} language.

        

        IMPORTANT: If you see actual code in the image, describe exactly what the code does, don't create a generic problem."""
        
        # Save image to a temporary file
        with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp:
            image.save(tmp.name, format="PNG")
            tmp_path = tmp.name
        
        try:
            response = self.agent.run(
                prompt,
                images=[{"filepath": tmp_path}]
            )
            return response.content
        except Exception as e:
            error_msg = str(e)
            if "503" in error_msg or "Service Unavailable" in error_msg:
                return """⚠️ **Gemini API Temporarily Unavailable**

                

The Gemini vision service is currently experiencing issues (503 error). This is a temporary server-side problem.



**What you can do:**

1. Wait a few minutes and try again

2. Check the Gemini API status page

3. Or describe your code/problem in text instead



**Based on common code patterns, I can still help you if you describe what you saw in the image in the text field below.**"""
            elif "API key" in error_msg:
                return "❌ **API Key Error**: Please check that your Gemini API key is valid and has access to vision features."
            elif "quota" in error_msg.lower() or "limit" in error_msg.lower():
                return "❌ **Rate Limit/Quota Error**: You've exceeded the API usage limits. Please wait or upgrade your plan."
            else:
                return f"❌ **Error processing image**: {error_msg}\n\nπŸ’‘ **Tip**: Try describing your code/problem in text instead."
        finally:
            # Clean up temporary file
            if os.path.exists(tmp_path):
                os.remove(tmp_path)
    
    def generate_code(self, problem_description: str, language: str = 'python') -> str:
        """Generate code for a given problem description in the specified language"""
        
        # Check if this is a multi-file project request
        multi_file_keywords = [
            'landing page', 'website', 'web app', 'mvp', 'portfolio', 
            'dashboard', 'form', 'html css js', 'html, css, js',
            'html css javascript', 'full website', 'complete website'
        ]
        
        is_multi_file = any(keyword in problem_description.lower() for keyword in multi_file_keywords)
        
        if is_multi_file and language in ['html', 'css', 'javascript']:
            return self._generate_multi_file_project(problem_description)
        
        # Language-specific requirements and templates
        language_specs = {
            'python': {
                'requirements': """1. Write clean, efficient Python code with proper documentation

2. Include proper function definitions with type hints

3. Handle edge cases appropriately

4. Include example usage if applicable

5. Only use standard library modules (no external dependencies)""",
                'format_instruction': "Format your response with the code in a ```python code block."
            },
            'javascript': {
                'requirements': """1. Write modern JavaScript (ES6+) code with proper documentation

2. Use appropriate function declarations/expressions

3. Handle edge cases appropriately

4. Include example usage if applicable

5. Use built-in JavaScript features and methods""",
                'format_instruction': "Format your response with the code in a ```javascript code block."
            },
            'typescript': {
                'requirements': """1. Write TypeScript code with proper type annotations

2. Use interfaces and types where appropriate

3. Handle edge cases appropriately

4. Include example usage if applicable

5. Follow TypeScript best practices""",
                'format_instruction': "Format your response with the code in a ```typescript code block."
            },
            'html': {
                'requirements': """1. Write semantic HTML5 code

2. Use proper HTML structure and tags

3. Include appropriate meta tags and attributes

4. Follow accessibility best practices

5. Use semantic elements where applicable""",
                'format_instruction': "Format your response with the code in a ```html code block."
            },
            'css': {
                'requirements': """1. Write clean, organized CSS code

2. Use appropriate selectors and properties

3. Follow CSS best practices and conventions

4. Include responsive design considerations if applicable

5. Use modern CSS features where appropriate""",
                'format_instruction': "Format your response with the code in a ```css code block."
            },
            'tsx': {
                'requirements': """1. Write React TypeScript (TSX) code with proper types

2. Use React hooks and modern patterns

3. Include proper component structure

4. Follow React and TypeScript best practices

5. Handle props and state appropriately""",
                'format_instruction': "Format your response with the code in a ```tsx code block."
            },
            'java': {
                'requirements': """1. Write clean Java code following conventions

2. Use appropriate access modifiers and OOP principles

3. Handle exceptions properly

4. Include proper class and method structure

5. Follow Java naming conventions""",
                'format_instruction': "Format your response with the code in a ```java code block."
            },
            'c': {
                'requirements': """1. Write clean C code with proper structure

2. Include necessary headers

3. Handle memory management carefully

4. Use appropriate data types and functions

5. Follow C programming conventions""",
                'format_instruction': "Format your response with the code in a ```c code block."
            },
            'cpp': {
                'requirements': """1. Write modern C++ code (C++11 or later)

2. Use appropriate STL containers and algorithms

3. Follow RAII principles and best practices

4. Include proper headers and namespaces

5. Handle exceptions and edge cases appropriately""",
                'format_instruction': "Format your response with the code in a ```cpp code block."
            }
        }
        
        spec = language_specs.get(language, language_specs['python'])
        
        prompt = f"""{self.system_prompt}



        Based on this problem description, write {language} code to solve it:

        

        {problem_description}

        

        Requirements:

        {spec['requirements']}

        

        {spec['format_instruction']}

        

        IMPORTANT: Generate code that exactly matches what the user requested. Do not add extra features or modify the requirements. Provide the exact output format requested."""
        
        try:
            response = self.agent.run(prompt)
            return response.content
        except Exception as e:
            return f"Error generating code: {str(e)}"
    
    def _generate_multi_file_project(self, problem_description: str) -> str:
        """Generate a complete multi-file web project (HTML, CSS, JS)"""
        prompt = f"""{self.system_prompt}



        Create a complete web project based on this description:

        {problem_description}

        

        Generate a fully functional website with:

        1. HTML file (index.html) - semantic, accessible structure

        2. CSS file (styles.css) - modern, responsive styling

        3. JavaScript file (script.js) - interactive functionality

        

        Requirements:

        - Make it responsive and mobile-friendly

        - Use modern web standards (HTML5, CSS3, ES6+)

        - Include proper meta tags and SEO basics

        - Add smooth animations and interactions

        - Follow accessibility best practices

        - Make it visually appealing and professional

        

        Format your response EXACTLY like this:

        

        ## πŸ“ Project Files

        

        ### πŸ“„ index.html

        ```html

        [Complete HTML code here]

        ```

        

        ### 🎨 styles.css

        ```css

        [Complete CSS code here]

        ```

        

        ### ⚑ script.js

        ```javascript

        [Complete JavaScript code here]

        ```

        

        ### πŸ“‹ Instructions

        [Brief setup and usage instructions]

        

        IMPORTANT: 

        - Generate complete, working code for each file

        - Make sure all files work together seamlessly

        - Include all necessary functionality requested

        - Use proper file structure and organization

        - Follow the exact format specified above"""
        
        try:
            response = self.agent.run(prompt)
            return response.content
        except Exception as e:
            return f"Error generating multi-file project: {str(e)}"
    
    def execute_and_explain(self, code: str, language: str = 'python') -> str:
        """Execute code and provide explanation of results"""
        # Extract code from markdown if needed
        code_blocks = [f'```{language}', f'```{language.lower()}', '```']
        extracted_code = code
        
        for block_start in code_blocks:
            if block_start in code:
                parts = code.split(block_start)
                if len(parts) > 1:
                    extracted_code = parts[1].split("```")[0].strip()
                    break
        
        # Execute the code
        result = self.executor.run_code(extracted_code, language)
        
        # Generate explanation
        if result["success"]:
            prompt = f"""{self.system_prompt}



            The following {language} code was executed successfully:

            

            ```{language}

            {extracted_code}

            ```

            

            Output: {result['output']}

            Logs: {result['logs']}

            

            Please explain what the code does and the execution results for this {language} program."""
        else:
            prompt = f"""{self.system_prompt}



            The following {language} code failed to execute:

            

            ```{language}

            {extracted_code}

            ```

            

            Error: {result['error']}

            Logs: {result['logs']}

            

            Please analyze the error and suggest fixes for this {language} code."""
        
        try:
            response = self.agent.run(prompt)
            return response.content
        except Exception as e:
            return f"Error explaining execution: {str(e)}\n\nRaw execution result: {str(result)}"
    
    def save_project_files(self, content: str, project_name: str = "generated_project") -> str:
        """Save multi-file project to disk and return the file paths"""
        if "## πŸ“ Project Files" not in content:
            return ""
        
        try:
            # Create project directory
            project_dir = os.path.join(os.getcwd(), project_name)
            os.makedirs(project_dir, exist_ok=True)
            
            saved_files = []
            
            # Extract and save HTML file
            if "### πŸ“„ index.html" in content:
                html_start = content.find("```html")
                if html_start != -1:
                    html_start = html_start + 7
                    html_end = content.find("```", html_start)
                    if html_end != -1:
                        html_content = content[html_start:html_end].strip()
                        html_path = os.path.join(project_dir, "index.html")
                        with open(html_path, 'w', encoding='utf-8') as f:
                            f.write(html_content)
                        saved_files.append("index.html")
            
            # Extract and save CSS file
            if "### 🎨 styles.css" in content:
                css_start = content.find("```css")
                if css_start != -1:
                    css_start = css_start + 6
                    css_end = content.find("```", css_start)
                    if css_end != -1:
                        css_content = content[css_start:css_end].strip()
                        css_path = os.path.join(project_dir, "styles.css")
                        with open(css_path, 'w', encoding='utf-8') as f:
                            f.write(css_content)
                        saved_files.append("styles.css")
            
            # Extract and save JavaScript file
            if "### ⚑ script.js" in content:
                js_start = content.find("```javascript")
                if js_start != -1:
                    js_start = js_start + 13
                    js_end = content.find("```", js_start)
                    if js_end != -1:
                        js_content = content[js_start:js_end].strip()
                        js_path = os.path.join(project_dir, "script.js")
                        with open(js_path, 'w', encoding='utf-8') as f:
                            f.write(js_content)
                        saved_files.append("script.js")
            
            if saved_files:
                return f"\n\n### πŸ’Ύ Files Saved Successfully!\nπŸ“ Project saved to: `{project_dir}`\nπŸ“‹ Files created: {', '.join(saved_files)}\n\n🌐 **To view your website**: Open `index.html` in your web browser!"
            
        except Exception as e:
            return f"\n\n❌ Error saving files: {str(e)}"
        
        return ""

def create_gradio_interface():
    """Create the Gradio interface for the coding agent"""
    
    agent_instance = None
    
    def process_input(api_key, language, image, text_input, save_files):
        nonlocal agent_instance
        
        # Initialize agent if not already done
        if not agent_instance:
            if not api_key:
                return "Please enter your Gemini API key first."
            try:
                agent_instance = MultimodalCodingAgent(api_key)
            except Exception as e:
                return f"Error initializing agent: {str(e)}"
        
        # Check if this is a multi-file project request
        multi_file_keywords = [
            'landing page', 'website', 'web app', 'mvp', 'portfolio', 
            'dashboard', 'form', 'html css js', 'html, css, js',
            'html css javascript', 'full website', 'complete website'
        ]
        
        input_text = text_input if text_input else ""
        is_multi_file_request = any(keyword in input_text.lower() for keyword in multi_file_keywords)
        
        # Process based on input type
        if image is not None:
            # Process image
            problem_description = agent_instance.process_image(image, language)
            
            # Check if image processing failed
            if "⚠️" in problem_description or "❌" in problem_description:
                return problem_description
            
            # Generate code from the problem description
            code = agent_instance.generate_code(problem_description, language)
            
            # Handle multi-file projects
            if is_multi_file_request or "## πŸ“ Project Files" in code:
                result = f"**Extracted Problem ({language.upper()}):**\n{problem_description}\n\n{code}"
                if save_files:
                    save_result = agent_instance.save_project_files(code, "extracted_project")
                    result += save_result
                return result
            
            # Execute and explain the code (if it's an executable language)
            elif language in ['python', 'javascript', 'typescript', 'tsx', 'java', 'c', 'cpp']:
                explanation = agent_instance.execute_and_explain(code, language)
                return f"**Extracted Problem ({language.upper()}):**\n{problem_description}\n\n**Generated Code:**\n{code}\n\n**Execution Results:**\n{explanation}"
            else:
                return f"**Extracted Problem ({language.upper()}):**\n{problem_description}\n\n**Generated Code:**\n{code}\n\n**Note:** {language.upper()} code cannot be executed but has been validated for syntax."
        
        elif text_input:
            # Generate code from text input
            code = agent_instance.generate_code(text_input, language)
            
            # Handle multi-file projects
            if is_multi_file_request or "## πŸ“ Project Files" in code:
                result = f"{code}"
                if save_files:
                    save_result = agent_instance.save_project_files(code, "generated_project")
                    result += save_result
                return result
            
            # Execute and explain the code (if it's an executable language)
            elif language in ['python', 'javascript', 'typescript', 'tsx', 'java', 'c', 'cpp']:
                explanation = agent_instance.execute_and_explain(code, language)
                return f"**Generated Code ({language.upper()}):**\n{code}\n\n**Execution Results:**\n{explanation}"
            else:
                return f"**Generated Code ({language.upper()}):**\n{code}\n\n**Note:** {language.upper()} code cannot be executed but has been validated for syntax."
        
        else:
            return "Please provide either an image or text input."
    
    # Create Gradio interface
    with gr.Blocks(title="Multimodal Coding Agent", theme=gr.themes.Soft()) as demo:
        gr.Markdown("# πŸš€ Multimodal Coding Agent")
        gr.Markdown("Upload an image of a coding problem or describe it in text, and I'll generate and execute a solution in your chosen programming language!")
        
        with gr.Row():
            api_key = gr.Textbox(
                label="πŸ”‘ Gemini API Key",
                type="password",
                placeholder="Enter your Gemini API key here",
                scale=3
            )
            language_dropdown = gr.Dropdown(
                label="πŸ’» Programming Language",
                choices=[
                    "python", "javascript", "typescript", "tsx", 
                    "java", "c", "cpp", "html", "css"
                ],
                value="python",
                scale=1
            )
        
        with gr.Row():
            with gr.Column():
                image_input = gr.Image(
                    label="πŸ“Έ Upload Image of Coding Problem",
                    type="pil"
                )
                text_input = gr.Textbox(
                    label="✏️ Or Describe Your Coding Problem",
                    lines=5,
                    placeholder="Example: Write a function to reverse a string\n\nFor web projects, try:\n- Make a MVP landing page using HTML, CSS and JS\n- Create a portfolio website\n- Build a responsive dashboard"
                )
                
                with gr.Row():
                    submit_btn = gr.Button("🎯 Generate & Execute Solution", variant="primary", scale=3)
                    save_files_checkbox = gr.Checkbox(
                        label="πŸ’Ύ Save files to disk",
                        value=False,
                        scale=1,
                        info="Auto-save multi-file projects"
                    )
            
            with gr.Column():
                output = gr.Markdown(label="πŸ“‹ Results", value="", height=600)
        
        # Language info display
        with gr.Row():
            gr.Markdown("""

            ### πŸ“š Supported Languages & Features:

            - **Python**: Full execution with safety restrictions

            - **JavaScript/TypeScript**: Requires Node.js/ts-node

            - **Java**: Requires JDK for compilation and execution

            - **C/C++**: Requires GCC/G++ compiler

            - **HTML/CSS**: Syntax validation + Multi-file web projects

            - **TSX**: React TypeScript components (requires setup)

            

            ### 🌐 Multi-File Web Projects:

            Use keywords like "landing page", "website", "MVP", "portfolio" to generate complete web projects with HTML, CSS, and JavaScript files automatically organized and saved!

            

            ### πŸ“Έ Image Processing Tips:

            - **If image processing fails (503 errors)**: This is usually temporary - wait a few minutes and retry

            - **Alternative**: Describe your code in text instead of uploading an image

            - **Best images**: Clear, high-contrast code screenshots work best

            

            ### ⚠️ Prerequisites:

            Make sure you have the required compilers/interpreters installed for code execution.

            """)
        
        submit_btn.click(
            fn=process_input,
            inputs=[api_key, language_dropdown, image_input, text_input, save_files_checkbox],
            outputs=output
        )
        
        # Add examples
        gr.Examples(
            examples=[
                ["python", None, "Write a function to find the factorial of a number", False],
                ["javascript", None, "Create a function to check if a string is a palindrome", False],
                ["html", None, "Make a MVP landing page using HTML, CSS and JS", True],
                ["html", None, "Create a responsive portfolio website", True],
                ["html", None, "Build a modern dashboard with navigation", True],
                ["java", None, "Write a class to implement a simple calculator", False],
                ["css", None, "Design a card component with hover effects", False],
            ],
            inputs=[language_dropdown, image_input, text_input, save_files_checkbox],
        )
    
    return demo

if __name__ == "__main__":
    demo = create_gradio_interface()
    demo.launch()