File size: 3,223 Bytes
3af908f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Local Python/bash code execution for the GAIA agent."""

from __future__ import annotations

import contextlib
import io
import os
import subprocess
import tempfile
import traceback
import uuid
from typing import Any


class CodeInterpreter:
    def __init__(self, max_execution_time: int = 30):
        self.max_execution_time = max_execution_time
        self.globals: dict[str, Any] = {
            "__builtins__": __builtins__,
        }

    def execute_code(self, code: str, language: str = "python") -> dict[str, Any]:
        language = language.lower()
        execution_id = str(uuid.uuid4())
        if language == "python":
            return self._execute_python(code, execution_id)
        if language == "bash":
            return self._execute_bash(code, execution_id)
        return {
            "execution_id": execution_id,
            "status": "error",
            "stdout": "",
            "stderr": f"Unsupported language: {language}",
            "result": None,
        }

    def _execute_python(self, code: str, execution_id: str) -> dict[str, Any]:
        output_buffer = io.StringIO()
        error_buffer = io.StringIO()
        result: dict[str, Any] = {
            "execution_id": execution_id,
            "status": "error",
            "stdout": "",
            "stderr": "",
            "result": None,
        }
        try:
            with contextlib.redirect_stdout(output_buffer), contextlib.redirect_stderr(
                error_buffer
            ):
                exec(code, self.globals)
            result["status"] = "success"
            result["stdout"] = output_buffer.getvalue()
            result["stderr"] = error_buffer.getvalue()
        except Exception:
            result["stderr"] = f"{error_buffer.getvalue()}\n{traceback.format_exc()}"
        return result

    def _execute_bash(self, code: str, execution_id: str) -> dict[str, Any]:
        try:
            completed = subprocess.run(
                code,
                shell=True,
                capture_output=True,
                text=True,
                timeout=self.max_execution_time,
            )
            return {
                "execution_id": execution_id,
                "status": "success" if completed.returncode == 0 else "error",
                "stdout": completed.stdout,
                "stderr": completed.stderr,
                "result": None,
            }
        except subprocess.TimeoutExpired:
            return {
                "execution_id": execution_id,
                "status": "error",
                "stdout": "",
                "stderr": "Execution timed out.",
                "result": None,
            }


_interpreter = CodeInterpreter()


def run_python(code: str) -> str:
    result = _interpreter.execute_code(code, language="python")
    parts: list[str] = []
    if result["status"] == "success":
        parts.append("Code executed successfully.")
        if result.get("stdout"):
            parts.append(f"Output:\n{result['stdout'].strip()}")
    else:
        parts.append("Code execution failed.")
        if result.get("stderr"):
            parts.append(f"Error:\n{result['stderr'].strip()}")
    return "\n".join(parts)[:12000]